1 // SPDX-License-Identifier: 0BSD 2 3 /////////////////////////////////////////////////////////////////////////////// 4 // 5 /// \file file_io.c 6 /// \brief File opening, unlinking, and closing 7 // 8 // Author: Lasse Collin 9 // 10 /////////////////////////////////////////////////////////////////////////////// 11 12 #include "private.h" 13 14 #include <fcntl.h> 15 16 #ifdef TUKLIB_DOSLIKE 17 # include <io.h> 18 #else 19 # include <poll.h> 20 # include <libgen.h> 21 static bool warn_fchown; 22 #endif 23 24 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMES) 25 # include <sys/time.h> 26 #elif defined(HAVE__FUTIME) 27 # include <sys/utime.h> 28 #elif defined(HAVE_UTIME) 29 # include <utime.h> 30 #endif 31 32 #include "tuklib_open_stdxxx.h" 33 34 #ifdef _MSC_VER 35 # ifdef _WIN64 36 typedef __int64 ssize_t; 37 # else 38 typedef int ssize_t; 39 # endif 40 41 typedef int mode_t; 42 # define S_IRUSR _S_IREAD 43 # define S_IWUSR _S_IWRITE 44 45 # define setmode _setmode 46 # define open _open 47 # define close _close 48 # define lseek _lseeki64 49 # define unlink _unlink 50 51 // The casts are to silence warnings. 52 // The sizes are known to be small enough. 53 # define read(fd, buf, size) _read(fd, buf, (unsigned int)(size)) 54 # define write(fd, buf, size) _write(fd, buf, (unsigned int)(size)) 55 56 # define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) 57 # define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) 58 #endif 59 60 #if defined(_WIN32) && !defined(__CYGWIN__) 61 # define fsync _commit 62 #endif 63 64 #ifndef O_BINARY 65 # define O_BINARY 0 66 #endif 67 68 #ifndef O_NOCTTY 69 # define O_NOCTTY 0 70 #endif 71 72 // In musl 1.2.5, O_SEARCH is defined to O_PATH. As of Linux 6.12, 73 // a file descriptor from open("dir", O_SEARCH | O_DIRECTORY) cannot be 74 // used with fsync() (fails with EBADF). musl 1.2.5 doesn't emulate it 75 // using /proc/self/fd. Even if it did, it might need to do it with 76 // fd = open("/proc/...", O_RDONLY); fsync(fd); which fails if the 77 // directory lacks read permission. Since we need a working fsync(), 78 // O_RDONLY imitates O_SEARCH better than O_PATH. 79 #if defined(O_SEARCH) && defined(O_PATH) && O_SEARCH == O_PATH 80 # undef O_SEARCH 81 #endif 82 83 #ifndef O_SEARCH 84 # define O_SEARCH O_RDONLY 85 #endif 86 87 #ifndef O_DIRECTORY 88 # define O_DIRECTORY 0 89 #endif 90 91 // Using this macro to silence a warning from gcc -Wlogical-op. 92 #if EAGAIN == EWOULDBLOCK 93 # define IS_EAGAIN_OR_EWOULDBLOCK(e) ((e) == EAGAIN) 94 #else 95 # define IS_EAGAIN_OR_EWOULDBLOCK(e) \ 96 ((e) == EAGAIN || (e) == EWOULDBLOCK) 97 #endif 98 99 100 typedef enum { 101 IO_WAIT_MORE, // Reading or writing is possible. 102 IO_WAIT_ERROR, // Error or user_abort 103 IO_WAIT_TIMEOUT, // poll() timed out 104 } io_wait_ret; 105 106 107 /// If true, try to create sparse files when decompressing. 108 static bool try_sparse = true; 109 110 #ifndef TUKLIB_DOSLIKE 111 /// File status flags of standard input. This is used by io_open_src() 112 /// and io_close_src(). 113 static int stdin_flags; 114 static bool restore_stdin_flags = false; 115 116 /// Original file status flags of standard output. This is used by 117 /// io_open_dest() and io_close_dest() to save and restore the flags. 118 static int stdout_flags; 119 static bool restore_stdout_flags = false; 120 121 /// Self-pipe used together with the user_abort variable to avoid 122 /// race conditions with signal handling. 123 static int user_abort_pipe[2]; 124 #endif 125 126 127 static bool io_write_buf(file_pair *pair, const uint8_t *buf, size_t size); 128 129 130 extern void 131 io_init(void) 132 { 133 // Make sure that stdin, stdout, and stderr are connected to 134 // a valid file descriptor. Exit immediately with exit code ERROR 135 // if we cannot make the file descriptors valid. Maybe we should 136 // print an error message, but our stderr could be screwed anyway. 137 tuklib_open_stdxxx(E_ERROR); 138 139 #ifndef TUKLIB_DOSLIKE 140 // If fchown() fails setting the owner, we warn about it only if 141 // we are root. 142 warn_fchown = geteuid() == 0; 143 144 // Create a pipe for the self-pipe trick. 145 if (pipe(user_abort_pipe)) 146 message_fatal(_("Error creating a pipe: %s"), 147 strerror(errno)); 148 149 // Make both ends of the pipe non-blocking. 150 for (unsigned i = 0; i < 2; ++i) { 151 int flags = fcntl(user_abort_pipe[i], F_GETFL); 152 if (flags == -1 || fcntl(user_abort_pipe[i], F_SETFL, 153 flags | O_NONBLOCK) == -1) 154 message_fatal(_("Error creating a pipe: %s"), 155 strerror(errno)); 156 } 157 #endif 158 159 #ifdef __DJGPP__ 160 // Avoid doing useless things when statting files. 161 // This isn't important but doesn't hurt. 162 _djstat_flags = _STAT_EXEC_EXT | _STAT_EXEC_MAGIC | _STAT_DIRSIZE; 163 #endif 164 165 return; 166 } 167 168 169 #ifndef TUKLIB_DOSLIKE 170 extern void 171 io_write_to_user_abort_pipe(void) 172 { 173 // If the write() fails, it's probably due to the pipe being full. 174 // Failing in that case is fine. If the reason is something else, 175 // there's not much we can do since this is called in a signal 176 // handler. So ignore the errors and try to avoid warnings with 177 // GCC and glibc when _FORTIFY_SOURCE=2 is used. 178 uint8_t b = '\0'; 179 const ssize_t ret = write(user_abort_pipe[1], &b, 1); 180 (void)ret; 181 return; 182 } 183 #endif 184 185 186 extern void 187 io_no_sparse(void) 188 { 189 try_sparse = false; 190 return; 191 } 192 193 194 #ifndef TUKLIB_DOSLIKE 195 /// \brief Waits for input or output to become available or for a signal 196 /// 197 /// This uses the self-pipe trick to avoid a race condition that can occur 198 /// if a signal is caught after user_abort has been checked but before e.g. 199 /// read() has been called. In that situation read() could block unless 200 /// non-blocking I/O is used. With non-blocking I/O something like select() 201 /// or poll() is needed to avoid a busy-wait loop, and the same race condition 202 /// pops up again. There are pselect() (POSIX-1.2001) and ppoll() (not in 203 /// POSIX) but neither is portable enough in 2013. The self-pipe trick is 204 /// old and very portable. 205 static io_wait_ret 206 io_wait(file_pair *pair, int timeout, bool is_reading) 207 { 208 struct pollfd pfd[2]; 209 210 if (is_reading) { 211 pfd[0].fd = pair->src_fd; 212 pfd[0].events = POLLIN; 213 } else { 214 pfd[0].fd = pair->dest_fd; 215 pfd[0].events = POLLOUT; 216 } 217 218 pfd[1].fd = user_abort_pipe[0]; 219 pfd[1].events = POLLIN; 220 221 while (true) { 222 const int ret = poll(pfd, 2, timeout); 223 224 if (user_abort) 225 return IO_WAIT_ERROR; 226 227 if (ret == -1) { 228 if (errno == EINTR || errno == EAGAIN) 229 continue; 230 231 message_error(_("%s: poll() failed: %s"), 232 tuklib_mask_nonprint(is_reading 233 ? pair->src_name 234 : pair->dest_name), 235 strerror(errno)); 236 return IO_WAIT_ERROR; 237 } 238 239 if (ret == 0) 240 return IO_WAIT_TIMEOUT; 241 242 if (pfd[0].revents != 0) 243 return IO_WAIT_MORE; 244 } 245 } 246 #endif 247 248 249 /// \brief Unlink a file 250 /// 251 /// This tries to verify that the file being unlinked really is the file that 252 /// we want to unlink by verifying device and inode numbers. There's still 253 /// a small unavoidable race, but this is much better than nothing (the file 254 /// could have been moved/replaced even hours earlier). 255 static void 256 io_unlink(const char *name, const struct stat *known_st) 257 { 258 #if defined(TUKLIB_DOSLIKE) 259 // On DOS-like systems, st_ino is meaningless, so don't bother 260 // testing it. Just silence a compiler warning. 261 (void)known_st; 262 #else 263 struct stat new_st; 264 265 // If --force was used, use stat() instead of lstat(). This way 266 // (de)compressing symlinks works correctly. However, it also means 267 // that xz cannot detect if a regular file foo is renamed to bar 268 // and then a symlink foo -> bar is created. Because of stat() 269 // instead of lstat(), xz will think that foo hasn't been replaced 270 // with another file. Thus, xz will remove foo even though it no 271 // longer is the same file that xz used when it started compressing. 272 // Probably it's not too bad though, so this doesn't need a more 273 // complex fix. 274 const int stat_ret = opt_force 275 ? stat(name, &new_st) : lstat(name, &new_st); 276 277 if (stat_ret 278 # ifdef __VMS 279 // st_ino is an array, and we don't want to 280 // compare st_dev at all. 281 || memcmp(&new_st.st_ino, &known_st->st_ino, 282 sizeof(new_st.st_ino)) != 0 283 # else 284 // Typical POSIX-like system 285 || new_st.st_dev != known_st->st_dev 286 || new_st.st_ino != known_st->st_ino 287 # endif 288 ) 289 // TRANSLATORS: When compression or decompression finishes, 290 // and xz is going to remove the source file, xz first checks 291 // if the source file still exists, and if it does, does its 292 // device and inode numbers match what xz saw when it opened 293 // the source file. If these checks fail, this message is 294 // shown, %s being the filename, and the file is not deleted. 295 // The check for device and inode numbers is there, because 296 // it is possible that the user has put a new file in place 297 // of the original file, and in that case it obviously 298 // shouldn't be removed. 299 message_warning(_("%s: File seems to have been moved, " 300 "not removing"), tuklib_mask_nonprint(name)); 301 else 302 #endif 303 // There's a race condition between lstat() and unlink() 304 // but at least we have tried to avoid removing wrong file. 305 if (unlink(name)) 306 message_warning(_("%s: Cannot remove: %s"), 307 tuklib_mask_nonprint(name), 308 strerror(errno)); 309 310 return; 311 } 312 313 314 /// \brief Copies owner/group and permissions 315 /// 316 /// \todo ACL and EA support 317 /// 318 static void 319 io_copy_attrs(const file_pair *pair) 320 { 321 // Skip chown and chmod on Windows. 322 #ifndef TUKLIB_DOSLIKE 323 // This function is more tricky than you may think at first. 324 // Blindly copying permissions may permit users to access the 325 // destination file who didn't have permission to access the 326 // source file. 327 328 // Try changing the owner of the file. If we aren't root or the owner 329 // isn't already us, fchown() probably doesn't succeed. We warn 330 // about failing fchown() only if we are root. 331 if (fchown(pair->dest_fd, pair->src_st.st_uid, (gid_t)(-1)) 332 && warn_fchown) 333 message_warning(_("%s: Cannot set the file owner: %s"), 334 tuklib_mask_nonprint(pair->dest_name), 335 strerror(errno)); 336 337 mode_t mode; 338 339 // With BSD semantics the new dest file may have a group that 340 // does not belong to the user. If the src file has the same gid 341 // nothing has to be done. Nevertheless OpenBSD fchown(2) fails 342 // in this case which seems to be POSIX compliant. As there is 343 // nothing to do, skip the system call. 344 if (pair->dest_st.st_gid != pair->src_st.st_gid 345 && fchown(pair->dest_fd, (uid_t)(-1), 346 pair->src_st.st_gid)) { 347 message_warning(_("%s: Cannot set the file group: %s"), 348 tuklib_mask_nonprint(pair->dest_name), 349 strerror(errno)); 350 // We can still safely copy some additional permissions: 351 // 'group' must be at least as strict as 'other' and 352 // also vice versa. 353 // 354 // NOTE: After this, the owner of the source file may 355 // get additional permissions. This shouldn't be too bad, 356 // because the owner would have had permission to chmod 357 // the original file anyway. 358 mode = ((pair->src_st.st_mode & 0070) >> 3) 359 & (pair->src_st.st_mode & 0007); 360 mode = (pair->src_st.st_mode & 0700) | (mode << 3) | mode; 361 } else { 362 // Drop the setuid, setgid, and sticky bits. 363 mode = pair->src_st.st_mode & 0777; 364 } 365 366 if (fchmod(pair->dest_fd, mode)) 367 message_warning(_("%s: Cannot set the file permissions: %s"), 368 tuklib_mask_nonprint(pair->dest_name), 369 strerror(errno)); 370 #endif 371 372 // Copy the timestamps. We have several possible ways to do this, of 373 // which some are better in both security and precision. 374 // 375 // First, get the nanosecond part of the timestamps. As of writing, 376 // it's not standardized by POSIX, and there are several names for 377 // the same thing in struct stat. 378 long atime_nsec; 379 long mtime_nsec; 380 381 # if defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC) 382 // GNU and Solaris 383 atime_nsec = pair->src_st.st_atim.tv_nsec; 384 mtime_nsec = pair->src_st.st_mtim.tv_nsec; 385 386 # elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC) 387 // BSD 388 atime_nsec = pair->src_st.st_atimespec.tv_nsec; 389 mtime_nsec = pair->src_st.st_mtimespec.tv_nsec; 390 391 # elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC) 392 // GNU and BSD without extensions 393 atime_nsec = pair->src_st.st_atimensec; 394 mtime_nsec = pair->src_st.st_mtimensec; 395 396 # elif defined(HAVE_STRUCT_STAT_ST_UATIME) 397 // Tru64 398 atime_nsec = pair->src_st.st_uatime * 1000; 399 mtime_nsec = pair->src_st.st_umtime * 1000; 400 401 # elif defined(HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC) 402 // UnixWare 403 atime_nsec = pair->src_st.st_atim.st__tim.tv_nsec; 404 mtime_nsec = pair->src_st.st_mtim.st__tim.tv_nsec; 405 406 # else 407 // Safe fallback 408 atime_nsec = 0; 409 mtime_nsec = 0; 410 # endif 411 412 // Construct a structure to hold the timestamps and call appropriate 413 // function to set the timestamps. 414 #if defined(HAVE_FUTIMENS) 415 // Use nanosecond precision. 416 struct timespec tv[2]; 417 tv[0].tv_sec = pair->src_st.st_atime; 418 tv[0].tv_nsec = atime_nsec; 419 tv[1].tv_sec = pair->src_st.st_mtime; 420 tv[1].tv_nsec = mtime_nsec; 421 422 (void)futimens(pair->dest_fd, tv); 423 424 #elif defined(HAVE_FUTIMES) || defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMES) 425 // Use microsecond precision. 426 struct timeval tv[2]; 427 tv[0].tv_sec = pair->src_st.st_atime; 428 tv[0].tv_usec = atime_nsec / 1000; 429 tv[1].tv_sec = pair->src_st.st_mtime; 430 tv[1].tv_usec = mtime_nsec / 1000; 431 432 # if defined(HAVE_FUTIMES) 433 (void)futimes(pair->dest_fd, tv); 434 # elif defined(HAVE_FUTIMESAT) 435 (void)futimesat(pair->dest_fd, NULL, tv); 436 # else 437 // Argh, no function to use a file descriptor to set the timestamp. 438 (void)utimes(pair->dest_name, tv); 439 # endif 440 441 #elif defined(HAVE__FUTIME) 442 // Use one-second precision with Windows-specific _futime(). 443 // We could use utime() too except that for some reason the 444 // timestamp will get reset at close(). With _futime() it works. 445 // This struct cannot be const as _futime() takes a non-const pointer. 446 struct _utimbuf buf = { 447 .actime = pair->src_st.st_atime, 448 .modtime = pair->src_st.st_mtime, 449 }; 450 451 // Avoid warnings. 452 (void)atime_nsec; 453 (void)mtime_nsec; 454 455 (void)_futime(pair->dest_fd, &buf); 456 457 #elif defined(HAVE_UTIME) 458 // Use one-second precision. utime() doesn't support using file 459 // descriptor either. Some systems have broken utime() prototype 460 // so don't make this const. 461 struct utimbuf buf = { 462 .actime = pair->src_st.st_atime, 463 .modtime = pair->src_st.st_mtime, 464 }; 465 466 // Avoid warnings. 467 (void)atime_nsec; 468 (void)mtime_nsec; 469 470 (void)utime(pair->dest_name, &buf); 471 #endif 472 473 return; 474 } 475 476 477 /// \brief Synchronizes the destination file to permanent storage 478 /// 479 /// \param pair File pair having the destination file open for writing 480 /// 481 /// \return On success, false is returned. On error, error message 482 /// is printed and true is returned. 483 static bool 484 io_sync_dest(file_pair *pair) 485 { 486 assert(pair->dest_fd != -1); 487 assert(pair->dest_fd != STDOUT_FILENO); 488 489 if (fsync(pair->dest_fd)) { 490 message_error(_("%s: Synchronizing the file failed: %s"), 491 tuklib_mask_nonprint(pair->dest_name), 492 strerror(errno)); 493 return true; 494 } 495 496 #if !defined(TUKLIB_DOSLIKE) && !defined(_AIX) && !defined(__QNX__) 497 // On AIX, this would fail with EBADF. 498 // On QNX, this would fail with EINVAL. 499 if (fsync(pair->dir_fd)) { 500 message_error(_("%s: Synchronizing the directory of " 501 "the file failed: %s"), 502 tuklib_mask_nonprint(pair->dest_name), 503 strerror(errno)); 504 return true; 505 } 506 #endif 507 508 return false; 509 } 510 511 512 /// Opens the source file. Returns false on success, true on error. 513 static bool 514 io_open_src_real(file_pair *pair) 515 { 516 // There's nothing to open when reading from stdin. 517 if (pair->src_name == stdin_filename) { 518 pair->src_fd = STDIN_FILENO; 519 #ifdef TUKLIB_DOSLIKE 520 setmode(STDIN_FILENO, O_BINARY); 521 #else 522 // Try to set stdin to non-blocking mode. It won't work 523 // e.g. on OpenBSD if stdout is e.g. /dev/null. In such 524 // case we proceed as if stdin were non-blocking anyway 525 // (in case of /dev/null it will be in practice). The 526 // same applies to stdout in io_open_dest_real(). 527 stdin_flags = fcntl(STDIN_FILENO, F_GETFL); 528 if (stdin_flags == -1) { 529 message_error(_("Error getting the file status flags " 530 "from standard input: %s"), 531 strerror(errno)); 532 return true; 533 } 534 535 if ((stdin_flags & O_NONBLOCK) == 0 536 && fcntl(STDIN_FILENO, F_SETFL, 537 stdin_flags | O_NONBLOCK) != -1) 538 restore_stdin_flags = true; 539 #endif 540 #ifdef HAVE_POSIX_FADVISE 541 // It will fail if stdin is a pipe and that's fine. 542 (void)posix_fadvise(STDIN_FILENO, 0, 0, 543 opt_mode == MODE_LIST 544 ? POSIX_FADV_RANDOM 545 : POSIX_FADV_SEQUENTIAL); 546 #endif 547 return false; 548 } 549 550 // Symlinks are not followed unless writing to stdout or --force 551 // or --keep was used. 552 const bool follow_symlinks 553 = opt_stdout || opt_force || opt_keep_original; 554 555 // We accept only regular files if we are writing the output 556 // to disk too. bzip2 allows overriding this with --force but 557 // gzip and xz don't. 558 const bool reg_files_only = !opt_stdout; 559 560 // Flags for open() 561 int flags = O_RDONLY | O_BINARY | O_NOCTTY; 562 563 #ifndef TUKLIB_DOSLIKE 564 // Use non-blocking I/O: 565 // - It prevents blocking when opening FIFOs and some other 566 // special files, which is good if we want to accept only 567 // regular files. 568 // - It can help avoiding some race conditions with signal handling. 569 flags |= O_NONBLOCK; 570 #endif 571 572 #if defined(O_NOFOLLOW) 573 if (!follow_symlinks) 574 flags |= O_NOFOLLOW; 575 #elif !defined(TUKLIB_DOSLIKE) 576 // Some POSIX-like systems lack O_NOFOLLOW (it's not required 577 // by POSIX). Check for symlinks with a separate lstat() on 578 // these systems. 579 if (!follow_symlinks) { 580 struct stat st; 581 if (lstat(pair->src_name, &st)) { 582 message_error(_("%s: %s"), 583 tuklib_mask_nonprint(pair->src_name), 584 strerror(errno)); 585 return true; 586 587 } else if (S_ISLNK(st.st_mode)) { 588 message_warning(_("%s: Is a symbolic link, " 589 "skipping"), 590 tuklib_mask_nonprint(pair->src_name)); 591 return true; 592 } 593 } 594 #else 595 // Avoid warnings. 596 (void)follow_symlinks; 597 #endif 598 599 // Try to open the file. Signals have been blocked so EINTR shouldn't 600 // be possible. 601 pair->src_fd = open(pair->src_name, flags); 602 603 if (pair->src_fd == -1) { 604 // Signals (that have a signal handler) have been blocked. 605 assert(errno != EINTR); 606 607 #ifdef O_NOFOLLOW 608 // Give an understandable error message if the reason 609 // for failing was that the file was a symbolic link. 610 // 611 // Note that at least Linux, OpenBSD, Solaris, and Darwin 612 // use ELOOP to indicate that O_NOFOLLOW was the reason 613 // that open() failed. Because there may be 614 // directories in the pathname, ELOOP may occur also 615 // because of a symlink loop in the directory part. 616 // So ELOOP doesn't tell us what actually went wrong, 617 // and this stupidity went into POSIX-1.2008 too. 618 // 619 // FreeBSD associates EMLINK with O_NOFOLLOW and 620 // Tru64 uses ENOTSUP. We use these directly here 621 // and skip the lstat() call and the associated race. 622 // I want to hear if there are other kernels that 623 // fail with something else than ELOOP with O_NOFOLLOW. 624 bool was_symlink = false; 625 626 # if defined(__FreeBSD__) || defined(__DragonFly__) 627 if (errno == EMLINK) 628 was_symlink = true; 629 630 # elif defined(__digital__) && defined(__unix__) 631 if (errno == ENOTSUP) 632 was_symlink = true; 633 634 # elif defined(__NetBSD__) 635 if (errno == EFTYPE) 636 was_symlink = true; 637 638 # else 639 if (errno == ELOOP && !follow_symlinks) { 640 const int saved_errno = errno; 641 struct stat st; 642 if (lstat(pair->src_name, &st) == 0 643 && S_ISLNK(st.st_mode)) 644 was_symlink = true; 645 646 errno = saved_errno; 647 } 648 # endif 649 650 if (was_symlink) 651 message_warning(_("%s: Is a symbolic link, " 652 "skipping"), 653 tuklib_mask_nonprint(pair->src_name)); 654 else 655 #endif 656 // Something else than O_NOFOLLOW failing 657 // (assuming that the race conditions didn't 658 // confuse us). 659 message_error(_("%s: %s"), 660 tuklib_mask_nonprint(pair->src_name), 661 strerror(errno)); 662 663 return true; 664 } 665 666 // Stat the source file. We need the result also when we copy 667 // the permissions, and when unlinking. 668 // 669 // NOTE: Use stat() instead of fstat() with DJGPP, because 670 // then we have a better chance to get st_ino value that can 671 // be used in io_open_dest_real() to prevent overwriting the 672 // source file. 673 #ifdef __DJGPP__ 674 if (stat(pair->src_name, &pair->src_st)) 675 goto error_msg; 676 #else 677 if (fstat(pair->src_fd, &pair->src_st)) 678 goto error_msg; 679 #endif 680 681 if (S_ISDIR(pair->src_st.st_mode)) { 682 message_warning(_("%s: Is a directory, skipping"), 683 tuklib_mask_nonprint(pair->src_name)); 684 goto error; 685 } 686 687 if (reg_files_only && !S_ISREG(pair->src_st.st_mode)) { 688 message_warning(_("%s: Not a regular file, skipping"), 689 tuklib_mask_nonprint(pair->src_name)); 690 goto error; 691 } 692 693 #ifndef TUKLIB_DOSLIKE 694 if (reg_files_only && !opt_force && !opt_keep_original) { 695 if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) { 696 // gzip rejects setuid and setgid files even 697 // when --force was used. bzip2 doesn't check 698 // for them, but calls fchown() after fchmod(), 699 // and many systems automatically drop setuid 700 // and setgid bits there. 701 // 702 // We accept setuid and setgid files if 703 // --force or --keep was used. We drop these bits 704 // explicitly in io_copy_attr(). 705 message_warning(_("%s: File has setuid or " 706 "setgid bit set, skipping"), 707 tuklib_mask_nonprint(pair->src_name)); 708 goto error; 709 } 710 711 if (pair->src_st.st_mode & S_ISVTX) { 712 message_warning(_("%s: File has sticky bit " 713 "set, skipping"), 714 tuklib_mask_nonprint(pair->src_name)); 715 goto error; 716 } 717 718 if (pair->src_st.st_nlink > 1) { 719 message_warning(_("%s: Input file has more " 720 "than one hard link, skipping"), 721 tuklib_mask_nonprint(pair->src_name)); 722 goto error; 723 } 724 } 725 726 // If it is something else than a regular file, wait until 727 // there is input available. This way reading from FIFOs 728 // will work when open() is used with O_NONBLOCK. 729 if (!S_ISREG(pair->src_st.st_mode)) { 730 signals_unblock(); 731 const io_wait_ret ret = io_wait(pair, -1, true); 732 signals_block(); 733 734 if (ret != IO_WAIT_MORE) 735 goto error; 736 } 737 #endif 738 739 #ifdef HAVE_POSIX_FADVISE 740 // It will fail with some special files like FIFOs but that is fine. 741 (void)posix_fadvise(pair->src_fd, 0, 0, 742 opt_mode == MODE_LIST 743 ? POSIX_FADV_RANDOM 744 : POSIX_FADV_SEQUENTIAL); 745 #endif 746 747 return false; 748 749 error_msg: 750 message_error(_("%s: %s"), tuklib_mask_nonprint(pair->src_name), 751 strerror(errno)); 752 error: 753 (void)close(pair->src_fd); 754 return true; 755 } 756 757 758 extern file_pair * 759 io_open_src(const char *src_name) 760 { 761 if (src_name[0] == '\0') { 762 message_error(_("Empty filename, skipping")); 763 return NULL; 764 } 765 766 // Since we have only one file open at a time, we can use 767 // a statically allocated structure. 768 static file_pair pair; 769 770 // This implicitly also initializes src_st.st_size to zero 771 // which is expected to be <= 0 by default. fstat() isn't 772 // called when reading from standard input but src_st.st_size 773 // is still read. 774 pair = (file_pair){ 775 .src_name = src_name, 776 .dest_name = NULL, 777 .src_fd = -1, 778 .dest_fd = -1, 779 #ifndef TUKLIB_DOSLIKE 780 .dir_fd = -1, 781 #endif 782 .src_eof = false, 783 .src_has_seen_input = false, 784 .flush_needed = false, 785 .dest_try_sparse = false, 786 .dest_pending_sparse = 0, 787 }; 788 789 // Block the signals, for which we have a custom signal handler, so 790 // that we don't need to worry about EINTR. 791 signals_block(); 792 const bool error = io_open_src_real(&pair); 793 signals_unblock(); 794 795 #ifdef ENABLE_SANDBOX 796 if (!error) 797 sandbox_enable_strict_if_allowed(pair.src_fd, 798 user_abort_pipe[0], user_abort_pipe[1]); 799 #endif 800 801 return error ? NULL : &pair; 802 } 803 804 805 /// \brief Closes source file of the file_pair structure 806 /// 807 /// \param pair File whose src_fd should be closed 808 /// \param success If true, the file will be removed from the disk if 809 /// closing succeeds and --keep hasn't been used. 810 static void 811 io_close_src(file_pair *pair, bool success) 812 { 813 #ifndef TUKLIB_DOSLIKE 814 if (restore_stdin_flags) { 815 assert(pair->src_fd == STDIN_FILENO); 816 817 restore_stdin_flags = false; 818 819 if (fcntl(STDIN_FILENO, F_SETFL, stdin_flags) == -1) 820 message_error(_("Error restoring the status flags " 821 "to standard input: %s"), 822 strerror(errno)); 823 } 824 #endif 825 826 if (pair->src_fd != STDIN_FILENO && pair->src_fd != -1) { 827 // Close the file before possibly unlinking it. On DOS-like 828 // systems this is always required since unlinking will fail 829 // if the file is open. On POSIX systems it usually works 830 // to unlink open files, but in some cases it doesn't and 831 // one gets EBUSY in errno. 832 // 833 // xz 5.2.2 and older unlinked the file before closing it 834 // (except on DOS-like systems). The old code didn't handle 835 // EBUSY and could fail e.g. on some CIFS shares. The 836 // advantage of unlinking before closing is negligible 837 // (avoids a race between close() and stat()/lstat() and 838 // unlink()), so let's keep this simple. 839 (void)close(pair->src_fd); 840 841 if (success && !opt_keep_original) 842 io_unlink(pair->src_name, &pair->src_st); 843 } 844 845 return; 846 } 847 848 849 static bool 850 io_open_dest_real(file_pair *pair) 851 { 852 if (opt_stdout || pair->src_fd == STDIN_FILENO) { 853 // We don't modify or free() this. 854 pair->dest_name = (char *)"(stdout)"; 855 pair->dest_fd = STDOUT_FILENO; 856 #ifdef TUKLIB_DOSLIKE 857 setmode(STDOUT_FILENO, O_BINARY); 858 #else 859 // Try to set O_NONBLOCK if it isn't already set. 860 // If it fails, we assume that stdout is non-blocking 861 // in practice. See the comments in io_open_src_real() 862 // for similar situation with stdin. 863 // 864 // NOTE: O_APPEND may be unset later in this function 865 // and it relies on stdout_flags being set here. 866 stdout_flags = fcntl(STDOUT_FILENO, F_GETFL); 867 if (stdout_flags == -1) { 868 message_error(_("Error getting the file status flags " 869 "from standard output: %s"), 870 strerror(errno)); 871 return true; 872 } 873 874 if ((stdout_flags & O_NONBLOCK) == 0 875 && fcntl(STDOUT_FILENO, F_SETFL, 876 stdout_flags | O_NONBLOCK) != -1) 877 restore_stdout_flags = true; 878 #endif 879 } else { 880 pair->dest_name = suffix_get_dest_name(pair->src_name); 881 if (pair->dest_name == NULL) 882 return true; 883 884 #ifndef TUKLIB_DOSLIKE 885 if (opt_synchronous) { 886 // Open the directory where the destination file will 887 // be created (the file descriptor is needed for 888 // fsync()). Do this before creating the destination 889 // file: 890 // 891 // - We currently have no files to clean up if 892 // opening the directory fails. (We aren't 893 // reading from stdin so there are no stdin_flags 894 // to restore either.) 895 // 896 // - Allocating memory with xstrdup() is safe only 897 // when we have nothing to clean up. 898 char *buf = xstrdup(pair->dest_name); 899 const char *dir_name = dirname(buf); 900 901 // O_NOCTTY and O_NONBLOCK are there in case 902 // O_DIRECTORY is 0 and dir_name doesn't refer 903 // to a directory. (We opened the source file 904 // already but directories might have been renamed 905 // after the source file was opened.) 906 pair->dir_fd = open(dir_name, O_SEARCH | O_DIRECTORY 907 | O_NOCTTY | O_NONBLOCK); 908 if (pair->dir_fd == -1) { 909 // Since we did open the source file 910 // successfully, we should rarely get here. 911 // Perhaps something has been renamed or 912 // had its permissions changed. 913 // 914 // In an odd case, the directory has write 915 // and search permissions but not read 916 // permission (d-wx------), and O_SEARCH is 917 // actually O_RDONLY. Then we would be able 918 // to create a new file and only the directory 919 // syncing would be impossible. But let's be 920 // strict about syncing and require users to 921 // explicitly disable it if they don't want it. 922 message_error(_("%s: Opening the directory " 923 "failed: %s"), 924 tuklib_mask_nonprint(dir_name), 925 strerror(errno)); 926 free(buf); 927 goto error; 928 } 929 930 free(buf); 931 } 932 #endif 933 934 #ifdef __DJGPP__ 935 struct stat st; 936 if (stat(pair->dest_name, &st) == 0) { 937 // Check that it isn't a special file like "prn". 938 if (st.st_dev == -1) { 939 message_error("%s: Refusing to write to " 940 "a DOS special file", 941 tuklib_mask_nonprint( 942 pair->dest_name)); 943 goto error; 944 } 945 946 // Check that we aren't overwriting the source file. 947 if (st.st_dev == pair->src_st.st_dev 948 && st.st_ino == pair->src_st.st_ino) { 949 message_error("%s: Output file is the same " 950 "as the input file", 951 tuklib_mask_nonprint( 952 pair->dest_name)); 953 goto error; 954 } 955 } 956 #endif 957 958 // If --force was used, unlink the target file first. 959 if (opt_force && unlink(pair->dest_name) && errno != ENOENT) { 960 message_error(_("%s: Cannot remove: %s"), 961 tuklib_mask_nonprint(pair->dest_name), 962 strerror(errno)); 963 goto error; 964 } 965 966 // Open the file. 967 int flags = O_WRONLY | O_BINARY | O_NOCTTY 968 | O_CREAT | O_EXCL; 969 #ifndef TUKLIB_DOSLIKE 970 flags |= O_NONBLOCK; 971 #endif 972 const mode_t mode = S_IRUSR | S_IWUSR; 973 pair->dest_fd = open(pair->dest_name, flags, mode); 974 975 if (pair->dest_fd == -1) { 976 message_error(_("%s: %s"), 977 tuklib_mask_nonprint(pair->dest_name), 978 strerror(errno)); 979 goto error; 980 } 981 982 // We could sync dir_fd now and close it. However, performance 983 // can be better if this is delayed until dest_fd has been 984 // synced in io_sync_dest(). 985 } 986 987 if (fstat(pair->dest_fd, &pair->dest_st)) { 988 // If fstat() really fails, we have a safe fallback here. 989 #if defined(__VMS) 990 pair->dest_st.st_ino[0] = 0; 991 pair->dest_st.st_ino[1] = 0; 992 pair->dest_st.st_ino[2] = 0; 993 #else 994 pair->dest_st.st_dev = 0; 995 pair->dest_st.st_ino = 0; 996 #endif 997 } 998 #if defined(TUKLIB_DOSLIKE) && !defined(__DJGPP__) 999 // Check that the output file is a regular file. We open with O_EXCL 1000 // but that doesn't prevent open()/_open() on Windows from opening 1001 // files like "con" or "nul". 1002 // 1003 // With DJGPP this check is done with stat() even before opening 1004 // the output file. That method or a variant of it doesn't work on 1005 // Windows because on Windows stat()/_stat64() sets st.st_mode so 1006 // that S_ISREG(st.st_mode) will be true even for special files. 1007 // With fstat()/_fstat64() it works. 1008 else if (pair->dest_fd != STDOUT_FILENO 1009 && !S_ISREG(pair->dest_st.st_mode)) { 1010 message_error(_("%s: Destination is not a regular file"), 1011 tuklib_mask_nonprint(pair->dest_name)); 1012 1013 // dest_fd needs to be reset to -1 to keep io_close() working. 1014 (void)close(pair->dest_fd); 1015 pair->dest_fd = -1; 1016 goto error; 1017 } 1018 #elif !defined(TUKLIB_DOSLIKE) 1019 else if (try_sparse && opt_mode == MODE_DECOMPRESS) { 1020 // When writing to standard output, we need to be extra 1021 // careful: 1022 // - It may be connected to something else than 1023 // a regular file. 1024 // - We aren't necessarily writing to a new empty file 1025 // or to the end of an existing file. 1026 // - O_APPEND may be active. 1027 // 1028 // TODO: I'm keeping this disabled for DOS-like systems 1029 // for now. FAT doesn't support sparse files, but NTFS 1030 // does, so maybe this should be enabled on Windows after 1031 // some testing. 1032 if (pair->dest_fd == STDOUT_FILENO) { 1033 if (!S_ISREG(pair->dest_st.st_mode)) 1034 return false; 1035 1036 if (stdout_flags & O_APPEND) { 1037 // Creating a sparse file is not possible 1038 // when O_APPEND is active (it's used by 1039 // shell's >> redirection). As I understand 1040 // it, it is safe to temporarily disable 1041 // O_APPEND in xz, because if someone 1042 // happened to write to the same file at the 1043 // same time, results would be bad anyway 1044 // (users shouldn't assume that xz uses any 1045 // specific block size when writing data). 1046 // 1047 // The write position may be something else 1048 // than the end of the file, so we must fix 1049 // it to start writing at the end of the file 1050 // to imitate O_APPEND. 1051 if (lseek(STDOUT_FILENO, 0, SEEK_END) == -1) 1052 return false; 1053 1054 // Construct the new file status flags. 1055 // If O_NONBLOCK was set earlier in this 1056 // function, it must be kept here too. 1057 int flags = stdout_flags & ~O_APPEND; 1058 if (restore_stdout_flags) 1059 flags |= O_NONBLOCK; 1060 1061 // If this fcntl() fails, we continue but won't 1062 // try to create sparse output. The original 1063 // flags will still be restored if needed (to 1064 // unset O_NONBLOCK) when the file is finished. 1065 if (fcntl(STDOUT_FILENO, F_SETFL, flags) == -1) 1066 return false; 1067 1068 // Disabling O_APPEND succeeded. Mark 1069 // that the flags should be restored 1070 // in io_close_dest(). (This may have already 1071 // been set when enabling O_NONBLOCK.) 1072 restore_stdout_flags = true; 1073 1074 } else if (lseek(STDOUT_FILENO, 0, SEEK_CUR) 1075 != pair->dest_st.st_size) { 1076 // Writing won't start exactly at the end 1077 // of the file. We cannot use sparse output, 1078 // because it would probably corrupt the file. 1079 return false; 1080 } 1081 } 1082 1083 pair->dest_try_sparse = true; 1084 } 1085 #endif 1086 1087 return false; 1088 1089 error: 1090 #ifndef TUKLIB_DOSLIKE 1091 // io_close() closes pair->dir_fd but let's do it here anyway. 1092 if (pair->dir_fd != -1) { 1093 (void)close(pair->dir_fd); 1094 pair->dir_fd = -1; 1095 } 1096 #endif 1097 1098 free(pair->dest_name); 1099 return true; 1100 } 1101 1102 1103 extern bool 1104 io_open_dest(file_pair *pair) 1105 { 1106 signals_block(); 1107 const bool ret = io_open_dest_real(pair); 1108 signals_unblock(); 1109 return ret; 1110 } 1111 1112 1113 /// \brief Closes destination file of the file_pair structure 1114 /// 1115 /// \param pair File whose dest_fd should be closed 1116 /// \param success If false, the file will be removed from the disk. 1117 /// 1118 /// \return If closing succeeds, false is returned. On error, an error 1119 /// message is printed and true is returned. 1120 static bool 1121 io_close_dest(file_pair *pair, bool success) 1122 { 1123 #ifndef TUKLIB_DOSLIKE 1124 // If io_open_dest() has disabled O_APPEND, restore it here. 1125 if (restore_stdout_flags) { 1126 assert(pair->dest_fd == STDOUT_FILENO); 1127 1128 restore_stdout_flags = false; 1129 1130 if (fcntl(STDOUT_FILENO, F_SETFL, stdout_flags) == -1) { 1131 message_error(_("Error restoring the O_APPEND flag " 1132 "to standard output: %s"), 1133 strerror(errno)); 1134 return true; 1135 } 1136 } 1137 #endif 1138 1139 if (pair->dest_fd == -1 || pair->dest_fd == STDOUT_FILENO) 1140 return false; 1141 1142 #ifndef TUKLIB_DOSLIKE 1143 // dir_fd was only used for syncing the directory. 1144 // Error checking was done when syncing. 1145 if (pair->dir_fd != -1) 1146 (void)close(pair->dir_fd); 1147 #endif 1148 1149 if (close(pair->dest_fd)) { 1150 message_error(_("%s: Closing the file failed: %s"), 1151 tuklib_mask_nonprint(pair->dest_name), 1152 strerror(errno)); 1153 1154 // Closing destination file failed, so we cannot trust its 1155 // contents. Get rid of junk: 1156 io_unlink(pair->dest_name, &pair->dest_st); 1157 free(pair->dest_name); 1158 return true; 1159 } 1160 1161 // If the operation using this file wasn't successful, we git rid 1162 // of the junk file. 1163 if (!success) 1164 io_unlink(pair->dest_name, &pair->dest_st); 1165 1166 free(pair->dest_name); 1167 1168 return false; 1169 } 1170 1171 1172 extern void 1173 io_close(file_pair *pair, bool success) 1174 { 1175 // Take care of sparseness at the end of the output file. 1176 if (success && pair->dest_try_sparse 1177 && pair->dest_pending_sparse > 0) { 1178 // Seek forward one byte less than the size of the pending 1179 // hole, then write one zero-byte. This way the file grows 1180 // to its correct size. An alternative would be to use 1181 // ftruncate() but that isn't portable enough (e.g. it 1182 // doesn't work with FAT on Linux; FAT isn't that important 1183 // since it doesn't support sparse files anyway, but we don't 1184 // want to create corrupt files on it). 1185 if (lseek(pair->dest_fd, pair->dest_pending_sparse - 1, 1186 SEEK_CUR) == -1) { 1187 message_error(_("%s: Seeking failed when trying " 1188 "to create a sparse file: %s"), 1189 tuklib_mask_nonprint(pair->dest_name), 1190 strerror(errno)); 1191 success = false; 1192 } else { 1193 const uint8_t zero[1] = { '\0' }; 1194 if (io_write_buf(pair, zero, 1)) 1195 success = false; 1196 } 1197 } 1198 1199 signals_block(); 1200 1201 if (success && pair->dest_fd != -1 && pair->dest_fd != STDOUT_FILENO) { 1202 // Copy the file attributes. This may produce warnings but 1203 // not errors so "success" isn't affected. 1204 io_copy_attrs(pair); 1205 1206 // Synchronize the file and its directory if needed. 1207 if (opt_synchronous) 1208 success = !io_sync_dest(pair); 1209 } 1210 1211 // Close the destination first. If it fails, we must not remove 1212 // the source file! 1213 if (io_close_dest(pair, success)) 1214 success = false; 1215 1216 // Close the source file, and unlink it if the operation using this 1217 // file pair was successful and we haven't requested to keep the 1218 // source file. 1219 io_close_src(pair, success); 1220 1221 signals_unblock(); 1222 1223 return; 1224 } 1225 1226 1227 extern void 1228 io_fix_src_pos(file_pair *pair, size_t rewind_size) 1229 { 1230 assert(rewind_size <= IO_BUFFER_SIZE); 1231 1232 if (rewind_size > 0) { 1233 // This doesn't need to work on unseekable file descriptors, 1234 // so just ignore possible errors. 1235 (void)lseek(pair->src_fd, -(off_t)(rewind_size), SEEK_CUR); 1236 } 1237 1238 return; 1239 } 1240 1241 1242 extern size_t 1243 io_read(file_pair *pair, io_buf *buf, size_t size) 1244 { 1245 assert(size <= IO_BUFFER_SIZE); 1246 1247 size_t pos = 0; 1248 1249 while (pos < size) { 1250 const ssize_t amount = read( 1251 pair->src_fd, buf->u8 + pos, size - pos); 1252 1253 if (amount == 0) { 1254 pair->src_eof = true; 1255 break; 1256 } 1257 1258 if (amount == -1) { 1259 if (errno == EINTR) { 1260 if (user_abort) 1261 return SIZE_MAX; 1262 1263 continue; 1264 } 1265 1266 #ifndef TUKLIB_DOSLIKE 1267 if (IS_EAGAIN_OR_EWOULDBLOCK(errno)) { 1268 // Disable the flush-timeout if no input has 1269 // been seen since the previous flush and thus 1270 // there would be nothing to flush after the 1271 // timeout expires (avoids busy waiting). 1272 const int timeout = pair->src_has_seen_input 1273 ? mytime_get_flush_timeout() 1274 : -1; 1275 1276 switch (io_wait(pair, timeout, true)) { 1277 case IO_WAIT_MORE: 1278 continue; 1279 1280 case IO_WAIT_ERROR: 1281 return SIZE_MAX; 1282 1283 case IO_WAIT_TIMEOUT: 1284 pair->flush_needed = true; 1285 return pos; 1286 1287 default: 1288 message_bug(); 1289 } 1290 } 1291 #endif 1292 1293 message_error(_("%s: Read error: %s"), 1294 tuklib_mask_nonprint(pair->src_name), 1295 strerror(errno)); 1296 1297 return SIZE_MAX; 1298 } 1299 1300 pos += (size_t)(amount); 1301 1302 if (!pair->src_has_seen_input) { 1303 pair->src_has_seen_input = true; 1304 mytime_set_flush_time(); 1305 } 1306 } 1307 1308 return pos; 1309 } 1310 1311 1312 extern bool 1313 io_seek_src(file_pair *pair, uint64_t pos) 1314 { 1315 // Caller must not attempt to seek past the end of the input file 1316 // (seeking to 100 in a 100-byte file is seeking to the end of 1317 // the file, not past the end of the file, and thus that is allowed). 1318 // 1319 // This also validates that pos can be safely cast to off_t. 1320 if (pos > (uint64_t)(pair->src_st.st_size)) 1321 message_bug(); 1322 1323 if (lseek(pair->src_fd, (off_t)(pos), SEEK_SET) == -1) { 1324 message_error(_("%s: Error seeking the file: %s"), 1325 tuklib_mask_nonprint(pair->src_name), 1326 strerror(errno)); 1327 return true; 1328 } 1329 1330 pair->src_eof = false; 1331 1332 return false; 1333 } 1334 1335 1336 extern bool 1337 io_pread(file_pair *pair, io_buf *buf, size_t size, uint64_t pos) 1338 { 1339 // Using lseek() and read() is more portable than pread() and 1340 // for us it is as good as real pread(). 1341 if (io_seek_src(pair, pos)) 1342 return true; 1343 1344 const size_t amount = io_read(pair, buf, size); 1345 if (amount == SIZE_MAX) 1346 return true; 1347 1348 if (amount != size) { 1349 message_error(_("%s: Unexpected end of file"), 1350 tuklib_mask_nonprint(pair->src_name)); 1351 return true; 1352 } 1353 1354 return false; 1355 } 1356 1357 1358 static bool 1359 is_sparse(const io_buf *buf) 1360 { 1361 assert(IO_BUFFER_SIZE % sizeof(uint64_t) == 0); 1362 1363 for (size_t i = 0; i < ARRAY_SIZE(buf->u64); ++i) 1364 if (buf->u64[i] != 0) 1365 return false; 1366 1367 return true; 1368 } 1369 1370 1371 static bool 1372 io_write_buf(file_pair *pair, const uint8_t *buf, size_t size) 1373 { 1374 assert(size <= IO_BUFFER_SIZE); 1375 1376 while (size > 0) { 1377 const ssize_t amount = write(pair->dest_fd, buf, size); 1378 if (amount == -1) { 1379 if (errno == EINTR) { 1380 if (user_abort) 1381 return true; 1382 1383 continue; 1384 } 1385 1386 #ifndef TUKLIB_DOSLIKE 1387 if (IS_EAGAIN_OR_EWOULDBLOCK(errno)) { 1388 if (io_wait(pair, -1, false) == IO_WAIT_MORE) 1389 continue; 1390 1391 return true; 1392 } 1393 #endif 1394 1395 #if defined(_WIN32) && !defined(__CYGWIN__) 1396 // On native Windows, broken pipe is reported as 1397 // EINVAL. Don't show an error message in this case. 1398 // Try: xz -dc bigfile.xz | head -n1 1399 if (errno == EINVAL 1400 && pair->dest_fd == STDOUT_FILENO) { 1401 // Emulate SIGPIPE by setting user_abort here. 1402 user_abort = true; 1403 set_exit_status(E_ERROR); 1404 return true; 1405 } 1406 #endif 1407 1408 // Handle broken pipe specially. gzip and bzip2 1409 // don't print anything on SIGPIPE. In addition, 1410 // gzip --quiet uses exit status 2 (warning) on 1411 // broken pipe instead of whatever raise(SIGPIPE) 1412 // would make it return. It is there to hide "Broken 1413 // pipe" message on some old shells (probably old 1414 // GNU bash). 1415 // 1416 // We don't do anything special with --quiet, which 1417 // is what bzip2 does too. If we get SIGPIPE, we 1418 // will handle it like other signals by setting 1419 // user_abort, and get EPIPE here. 1420 if (errno != EPIPE) 1421 message_error(_("%s: Write error: %s"), 1422 tuklib_mask_nonprint(pair->dest_name), 1423 strerror(errno)); 1424 1425 return true; 1426 } 1427 1428 buf += (size_t)(amount); 1429 size -= (size_t)(amount); 1430 } 1431 1432 return false; 1433 } 1434 1435 1436 extern bool 1437 io_write(file_pair *pair, const io_buf *buf, size_t size) 1438 { 1439 assert(size <= IO_BUFFER_SIZE); 1440 1441 if (pair->dest_try_sparse) { 1442 // Check if the block is sparse (contains only zeros). If it 1443 // sparse, we just store the amount and return. We will take 1444 // care of actually skipping over the hole when we hit the 1445 // next data block or close the file. 1446 // 1447 // Since io_close() requires that dest_pending_sparse > 0 1448 // if the file ends with sparse block, we must also return 1449 // if size == 0 to avoid doing the lseek(). 1450 if (size == IO_BUFFER_SIZE) { 1451 // Even if the block was sparse, treat it as non-sparse 1452 // if the pending sparse amount is large compared to 1453 // the size of off_t. In practice this only matters 1454 // on 32-bit systems where off_t isn't always 64 bits. 1455 const off_t pending_max 1456 = (off_t)(1) << (sizeof(off_t) * CHAR_BIT - 2); 1457 if (is_sparse(buf) && pair->dest_pending_sparse 1458 < pending_max) { 1459 pair->dest_pending_sparse += (off_t)(size); 1460 return false; 1461 } 1462 } else if (size == 0) { 1463 return false; 1464 } 1465 1466 // This is not a sparse block. If we have a pending hole, 1467 // skip it now. 1468 if (pair->dest_pending_sparse > 0) { 1469 if (lseek(pair->dest_fd, pair->dest_pending_sparse, 1470 SEEK_CUR) == -1) { 1471 message_error(_("%s: Seeking failed when " 1472 "trying to create a sparse " 1473 "file: %s"), 1474 tuklib_mask_nonprint( 1475 pair->dest_name), 1476 strerror(errno)); 1477 return true; 1478 } 1479 1480 pair->dest_pending_sparse = 0; 1481 } 1482 } 1483 1484 return io_write_buf(pair, buf->u8, size); 1485 } 1486