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
io_init(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
io_write_to_user_abort_pipe(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
io_no_sparse(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
io_wait(file_pair * pair,int timeout,bool is_reading)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
io_unlink(const char * name,const struct stat * known_st)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
io_copy_attrs(const file_pair * pair)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
io_sync_dest(file_pair * pair)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 #ifndef TUKLIB_DOSLIKE
497 if (fsync(pair->dir_fd)) {
498 message_error(_("%s: Synchronizing the directory of "
499 "the file failed: %s"),
500 tuklib_mask_nonprint(pair->dest_name),
501 strerror(errno));
502 return true;
503 }
504 #endif
505
506 return false;
507 }
508
509
510 /// Opens the source file. Returns false on success, true on error.
511 static bool
io_open_src_real(file_pair * pair)512 io_open_src_real(file_pair *pair)
513 {
514 // There's nothing to open when reading from stdin.
515 if (pair->src_name == stdin_filename) {
516 pair->src_fd = STDIN_FILENO;
517 #ifdef TUKLIB_DOSLIKE
518 setmode(STDIN_FILENO, O_BINARY);
519 #else
520 // Try to set stdin to non-blocking mode. It won't work
521 // e.g. on OpenBSD if stdout is e.g. /dev/null. In such
522 // case we proceed as if stdin were non-blocking anyway
523 // (in case of /dev/null it will be in practice). The
524 // same applies to stdout in io_open_dest_real().
525 stdin_flags = fcntl(STDIN_FILENO, F_GETFL);
526 if (stdin_flags == -1) {
527 message_error(_("Error getting the file status flags "
528 "from standard input: %s"),
529 strerror(errno));
530 return true;
531 }
532
533 if ((stdin_flags & O_NONBLOCK) == 0
534 && fcntl(STDIN_FILENO, F_SETFL,
535 stdin_flags | O_NONBLOCK) != -1)
536 restore_stdin_flags = true;
537 #endif
538 #ifdef HAVE_POSIX_FADVISE
539 // It will fail if stdin is a pipe and that's fine.
540 (void)posix_fadvise(STDIN_FILENO, 0, 0,
541 opt_mode == MODE_LIST
542 ? POSIX_FADV_RANDOM
543 : POSIX_FADV_SEQUENTIAL);
544 #endif
545 return false;
546 }
547
548 // Symlinks are not followed unless writing to stdout or --force
549 // or --keep was used.
550 const bool follow_symlinks
551 = opt_stdout || opt_force || opt_keep_original;
552
553 // We accept only regular files if we are writing the output
554 // to disk too. bzip2 allows overriding this with --force but
555 // gzip and xz don't.
556 const bool reg_files_only = !opt_stdout;
557
558 // Flags for open()
559 int flags = O_RDONLY | O_BINARY | O_NOCTTY;
560
561 #ifndef TUKLIB_DOSLIKE
562 // Use non-blocking I/O:
563 // - It prevents blocking when opening FIFOs and some other
564 // special files, which is good if we want to accept only
565 // regular files.
566 // - It can help avoiding some race conditions with signal handling.
567 flags |= O_NONBLOCK;
568 #endif
569
570 #if defined(O_NOFOLLOW)
571 if (!follow_symlinks)
572 flags |= O_NOFOLLOW;
573 #elif !defined(TUKLIB_DOSLIKE)
574 // Some POSIX-like systems lack O_NOFOLLOW (it's not required
575 // by POSIX). Check for symlinks with a separate lstat() on
576 // these systems.
577 if (!follow_symlinks) {
578 struct stat st;
579 if (lstat(pair->src_name, &st)) {
580 message_error(_("%s: %s"),
581 tuklib_mask_nonprint(pair->src_name),
582 strerror(errno));
583 return true;
584
585 } else if (S_ISLNK(st.st_mode)) {
586 message_warning(_("%s: Is a symbolic link, "
587 "skipping"),
588 tuklib_mask_nonprint(pair->src_name));
589 return true;
590 }
591 }
592 #else
593 // Avoid warnings.
594 (void)follow_symlinks;
595 #endif
596
597 // Try to open the file. Signals have been blocked so EINTR shouldn't
598 // be possible.
599 pair->src_fd = open(pair->src_name, flags);
600
601 if (pair->src_fd == -1) {
602 // Signals (that have a signal handler) have been blocked.
603 assert(errno != EINTR);
604
605 #ifdef O_NOFOLLOW
606 // Give an understandable error message if the reason
607 // for failing was that the file was a symbolic link.
608 //
609 // Note that at least Linux, OpenBSD, Solaris, and Darwin
610 // use ELOOP to indicate that O_NOFOLLOW was the reason
611 // that open() failed. Because there may be
612 // directories in the pathname, ELOOP may occur also
613 // because of a symlink loop in the directory part.
614 // So ELOOP doesn't tell us what actually went wrong,
615 // and this stupidity went into POSIX-1.2008 too.
616 //
617 // FreeBSD associates EMLINK with O_NOFOLLOW and
618 // Tru64 uses ENOTSUP. We use these directly here
619 // and skip the lstat() call and the associated race.
620 // I want to hear if there are other kernels that
621 // fail with something else than ELOOP with O_NOFOLLOW.
622 bool was_symlink = false;
623
624 # if defined(__FreeBSD__) || defined(__DragonFly__)
625 if (errno == EMLINK)
626 was_symlink = true;
627
628 # elif defined(__digital__) && defined(__unix__)
629 if (errno == ENOTSUP)
630 was_symlink = true;
631
632 # elif defined(__NetBSD__)
633 if (errno == EFTYPE)
634 was_symlink = true;
635
636 # else
637 if (errno == ELOOP && !follow_symlinks) {
638 const int saved_errno = errno;
639 struct stat st;
640 if (lstat(pair->src_name, &st) == 0
641 && S_ISLNK(st.st_mode))
642 was_symlink = true;
643
644 errno = saved_errno;
645 }
646 # endif
647
648 if (was_symlink)
649 message_warning(_("%s: Is a symbolic link, "
650 "skipping"),
651 tuklib_mask_nonprint(pair->src_name));
652 else
653 #endif
654 // Something else than O_NOFOLLOW failing
655 // (assuming that the race conditions didn't
656 // confuse us).
657 message_error(_("%s: %s"),
658 tuklib_mask_nonprint(pair->src_name),
659 strerror(errno));
660
661 return true;
662 }
663
664 // Stat the source file. We need the result also when we copy
665 // the permissions, and when unlinking.
666 //
667 // NOTE: Use stat() instead of fstat() with DJGPP, because
668 // then we have a better chance to get st_ino value that can
669 // be used in io_open_dest_real() to prevent overwriting the
670 // source file.
671 #ifdef __DJGPP__
672 if (stat(pair->src_name, &pair->src_st))
673 goto error_msg;
674 #else
675 if (fstat(pair->src_fd, &pair->src_st))
676 goto error_msg;
677 #endif
678
679 if (S_ISDIR(pair->src_st.st_mode)) {
680 message_warning(_("%s: Is a directory, skipping"),
681 tuklib_mask_nonprint(pair->src_name));
682 goto error;
683 }
684
685 if (reg_files_only && !S_ISREG(pair->src_st.st_mode)) {
686 message_warning(_("%s: Not a regular file, skipping"),
687 tuklib_mask_nonprint(pair->src_name));
688 goto error;
689 }
690
691 #ifndef TUKLIB_DOSLIKE
692 if (reg_files_only && !opt_force && !opt_keep_original) {
693 if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) {
694 // gzip rejects setuid and setgid files even
695 // when --force was used. bzip2 doesn't check
696 // for them, but calls fchown() after fchmod(),
697 // and many systems automatically drop setuid
698 // and setgid bits there.
699 //
700 // We accept setuid and setgid files if
701 // --force or --keep was used. We drop these bits
702 // explicitly in io_copy_attr().
703 message_warning(_("%s: File has setuid or "
704 "setgid bit set, skipping"),
705 tuklib_mask_nonprint(pair->src_name));
706 goto error;
707 }
708
709 if (pair->src_st.st_mode & S_ISVTX) {
710 message_warning(_("%s: File has sticky bit "
711 "set, skipping"),
712 tuklib_mask_nonprint(pair->src_name));
713 goto error;
714 }
715
716 if (pair->src_st.st_nlink > 1) {
717 message_warning(_("%s: Input file has more "
718 "than one hard link, skipping"),
719 tuklib_mask_nonprint(pair->src_name));
720 goto error;
721 }
722 }
723
724 // If it is something else than a regular file, wait until
725 // there is input available. This way reading from FIFOs
726 // will work when open() is used with O_NONBLOCK.
727 if (!S_ISREG(pair->src_st.st_mode)) {
728 signals_unblock();
729 const io_wait_ret ret = io_wait(pair, -1, true);
730 signals_block();
731
732 if (ret != IO_WAIT_MORE)
733 goto error;
734 }
735 #endif
736
737 #ifdef HAVE_POSIX_FADVISE
738 // It will fail with some special files like FIFOs but that is fine.
739 (void)posix_fadvise(pair->src_fd, 0, 0,
740 opt_mode == MODE_LIST
741 ? POSIX_FADV_RANDOM
742 : POSIX_FADV_SEQUENTIAL);
743 #endif
744
745 return false;
746
747 error_msg:
748 message_error(_("%s: %s"), tuklib_mask_nonprint(pair->src_name),
749 strerror(errno));
750 error:
751 (void)close(pair->src_fd);
752 return true;
753 }
754
755
756 extern file_pair *
io_open_src(const char * src_name)757 io_open_src(const char *src_name)
758 {
759 if (src_name[0] == '\0') {
760 message_error(_("Empty filename, skipping"));
761 return NULL;
762 }
763
764 // Since we have only one file open at a time, we can use
765 // a statically allocated structure.
766 static file_pair pair;
767
768 // This implicitly also initializes src_st.st_size to zero
769 // which is expected to be <= 0 by default. fstat() isn't
770 // called when reading from standard input but src_st.st_size
771 // is still read.
772 pair = (file_pair){
773 .src_name = src_name,
774 .dest_name = NULL,
775 .src_fd = -1,
776 .dest_fd = -1,
777 #ifndef TUKLIB_DOSLIKE
778 .dir_fd = -1,
779 #endif
780 .src_eof = false,
781 .src_has_seen_input = false,
782 .flush_needed = false,
783 .dest_try_sparse = false,
784 .dest_pending_sparse = 0,
785 };
786
787 // Block the signals, for which we have a custom signal handler, so
788 // that we don't need to worry about EINTR.
789 signals_block();
790 const bool error = io_open_src_real(&pair);
791 signals_unblock();
792
793 #ifdef ENABLE_SANDBOX
794 if (!error)
795 sandbox_enable_strict_if_allowed(pair.src_fd,
796 user_abort_pipe[0], user_abort_pipe[1]);
797 #endif
798
799 return error ? NULL : &pair;
800 }
801
802
803 /// \brief Closes source file of the file_pair structure
804 ///
805 /// \param pair File whose src_fd should be closed
806 /// \param success If true, the file will be removed from the disk if
807 /// closing succeeds and --keep hasn't been used.
808 static void
io_close_src(file_pair * pair,bool success)809 io_close_src(file_pair *pair, bool success)
810 {
811 #ifndef TUKLIB_DOSLIKE
812 if (restore_stdin_flags) {
813 assert(pair->src_fd == STDIN_FILENO);
814
815 restore_stdin_flags = false;
816
817 if (fcntl(STDIN_FILENO, F_SETFL, stdin_flags) == -1)
818 message_error(_("Error restoring the status flags "
819 "to standard input: %s"),
820 strerror(errno));
821 }
822 #endif
823
824 if (pair->src_fd != STDIN_FILENO && pair->src_fd != -1) {
825 // Close the file before possibly unlinking it. On DOS-like
826 // systems this is always required since unlinking will fail
827 // if the file is open. On POSIX systems it usually works
828 // to unlink open files, but in some cases it doesn't and
829 // one gets EBUSY in errno.
830 //
831 // xz 5.2.2 and older unlinked the file before closing it
832 // (except on DOS-like systems). The old code didn't handle
833 // EBUSY and could fail e.g. on some CIFS shares. The
834 // advantage of unlinking before closing is negligible
835 // (avoids a race between close() and stat()/lstat() and
836 // unlink()), so let's keep this simple.
837 (void)close(pair->src_fd);
838
839 if (success && !opt_keep_original)
840 io_unlink(pair->src_name, &pair->src_st);
841 }
842
843 return;
844 }
845
846
847 static bool
io_open_dest_real(file_pair * pair)848 io_open_dest_real(file_pair *pair)
849 {
850 if (opt_stdout || pair->src_fd == STDIN_FILENO) {
851 // We don't modify or free() this.
852 pair->dest_name = (char *)"(stdout)";
853 pair->dest_fd = STDOUT_FILENO;
854 #ifdef TUKLIB_DOSLIKE
855 setmode(STDOUT_FILENO, O_BINARY);
856 #else
857 // Try to set O_NONBLOCK if it isn't already set.
858 // If it fails, we assume that stdout is non-blocking
859 // in practice. See the comments in io_open_src_real()
860 // for similar situation with stdin.
861 //
862 // NOTE: O_APPEND may be unset later in this function
863 // and it relies on stdout_flags being set here.
864 stdout_flags = fcntl(STDOUT_FILENO, F_GETFL);
865 if (stdout_flags == -1) {
866 message_error(_("Error getting the file status flags "
867 "from standard output: %s"),
868 strerror(errno));
869 return true;
870 }
871
872 if ((stdout_flags & O_NONBLOCK) == 0
873 && fcntl(STDOUT_FILENO, F_SETFL,
874 stdout_flags | O_NONBLOCK) != -1)
875 restore_stdout_flags = true;
876 #endif
877 } else {
878 pair->dest_name = suffix_get_dest_name(pair->src_name);
879 if (pair->dest_name == NULL)
880 return true;
881
882 #ifndef TUKLIB_DOSLIKE
883 if (opt_synchronous) {
884 // Open the directory where the destination file will
885 // be created (the file descriptor is needed for
886 // fsync()). Do this before creating the destination
887 // file:
888 //
889 // - We currently have no files to clean up if
890 // opening the directory fails. (We aren't
891 // reading from stdin so there are no stdin_flags
892 // to restore either.)
893 //
894 // - Allocating memory with xstrdup() is safe only
895 // when we have nothing to clean up.
896 char *buf = xstrdup(pair->dest_name);
897 const char *dir_name = dirname(buf);
898
899 // O_NOCTTY and O_NONBLOCK are there in case
900 // O_DIRECTORY is 0 and dir_name doesn't refer
901 // to a directory. (We opened the source file
902 // already but directories might have been renamed
903 // after the source file was opened.)
904 pair->dir_fd = open(dir_name, O_SEARCH | O_DIRECTORY
905 | O_NOCTTY | O_NONBLOCK);
906 if (pair->dir_fd == -1) {
907 // Since we did open the source file
908 // successfully, we should rarely get here.
909 // Perhaps something has been renamed or
910 // had its permissions changed.
911 //
912 // In an odd case, the directory has write
913 // and search permissions but not read
914 // permission (d-wx------), and O_SEARCH is
915 // actually O_RDONLY. Then we would be able
916 // to create a new file and only the directory
917 // syncing would be impossible. But let's be
918 // strict about syncing and require users to
919 // explicitly disable it if they don't want it.
920 message_error(_("%s: Opening the directory "
921 "failed: %s"),
922 tuklib_mask_nonprint(dir_name),
923 strerror(errno));
924 free(buf);
925 goto error;
926 }
927
928 free(buf);
929 }
930 #endif
931
932 #ifdef __DJGPP__
933 struct stat st;
934 if (stat(pair->dest_name, &st) == 0) {
935 // Check that it isn't a special file like "prn".
936 if (st.st_dev == -1) {
937 message_error("%s: Refusing to write to "
938 "a DOS special file",
939 tuklib_mask_nonprint(
940 pair->dest_name));
941 goto error;
942 }
943
944 // Check that we aren't overwriting the source file.
945 if (st.st_dev == pair->src_st.st_dev
946 && st.st_ino == pair->src_st.st_ino) {
947 message_error("%s: Output file is the same "
948 "as the input file",
949 tuklib_mask_nonprint(
950 pair->dest_name));
951 goto error;
952 }
953 }
954 #endif
955
956 // If --force was used, unlink the target file first.
957 if (opt_force && unlink(pair->dest_name) && errno != ENOENT) {
958 message_error(_("%s: Cannot remove: %s"),
959 tuklib_mask_nonprint(pair->dest_name),
960 strerror(errno));
961 goto error;
962 }
963
964 // Open the file.
965 int flags = O_WRONLY | O_BINARY | O_NOCTTY
966 | O_CREAT | O_EXCL;
967 #ifndef TUKLIB_DOSLIKE
968 flags |= O_NONBLOCK;
969 #endif
970 const mode_t mode = S_IRUSR | S_IWUSR;
971 pair->dest_fd = open(pair->dest_name, flags, mode);
972
973 if (pair->dest_fd == -1) {
974 message_error(_("%s: %s"),
975 tuklib_mask_nonprint(pair->dest_name),
976 strerror(errno));
977 goto error;
978 }
979
980 // We could sync dir_fd now and close it. However, performance
981 // can be better if this is delayed until dest_fd has been
982 // synced in io_sync_dest().
983 }
984
985 if (fstat(pair->dest_fd, &pair->dest_st)) {
986 // If fstat() really fails, we have a safe fallback here.
987 #if defined(__VMS)
988 pair->dest_st.st_ino[0] = 0;
989 pair->dest_st.st_ino[1] = 0;
990 pair->dest_st.st_ino[2] = 0;
991 #else
992 pair->dest_st.st_dev = 0;
993 pair->dest_st.st_ino = 0;
994 #endif
995 }
996 #if defined(TUKLIB_DOSLIKE) && !defined(__DJGPP__)
997 // Check that the output file is a regular file. We open with O_EXCL
998 // but that doesn't prevent open()/_open() on Windows from opening
999 // files like "con" or "nul".
1000 //
1001 // With DJGPP this check is done with stat() even before opening
1002 // the output file. That method or a variant of it doesn't work on
1003 // Windows because on Windows stat()/_stat64() sets st.st_mode so
1004 // that S_ISREG(st.st_mode) will be true even for special files.
1005 // With fstat()/_fstat64() it works.
1006 else if (pair->dest_fd != STDOUT_FILENO
1007 && !S_ISREG(pair->dest_st.st_mode)) {
1008 message_error(_("%s: Destination is not a regular file"),
1009 tuklib_mask_nonprint(pair->dest_name));
1010
1011 // dest_fd needs to be reset to -1 to keep io_close() working.
1012 (void)close(pair->dest_fd);
1013 pair->dest_fd = -1;
1014 goto error;
1015 }
1016 #elif !defined(TUKLIB_DOSLIKE)
1017 else if (try_sparse && opt_mode == MODE_DECOMPRESS) {
1018 // When writing to standard output, we need to be extra
1019 // careful:
1020 // - It may be connected to something else than
1021 // a regular file.
1022 // - We aren't necessarily writing to a new empty file
1023 // or to the end of an existing file.
1024 // - O_APPEND may be active.
1025 //
1026 // TODO: I'm keeping this disabled for DOS-like systems
1027 // for now. FAT doesn't support sparse files, but NTFS
1028 // does, so maybe this should be enabled on Windows after
1029 // some testing.
1030 if (pair->dest_fd == STDOUT_FILENO) {
1031 if (!S_ISREG(pair->dest_st.st_mode))
1032 return false;
1033
1034 if (stdout_flags & O_APPEND) {
1035 // Creating a sparse file is not possible
1036 // when O_APPEND is active (it's used by
1037 // shell's >> redirection). As I understand
1038 // it, it is safe to temporarily disable
1039 // O_APPEND in xz, because if someone
1040 // happened to write to the same file at the
1041 // same time, results would be bad anyway
1042 // (users shouldn't assume that xz uses any
1043 // specific block size when writing data).
1044 //
1045 // The write position may be something else
1046 // than the end of the file, so we must fix
1047 // it to start writing at the end of the file
1048 // to imitate O_APPEND.
1049 if (lseek(STDOUT_FILENO, 0, SEEK_END) == -1)
1050 return false;
1051
1052 // Construct the new file status flags.
1053 // If O_NONBLOCK was set earlier in this
1054 // function, it must be kept here too.
1055 int flags = stdout_flags & ~O_APPEND;
1056 if (restore_stdout_flags)
1057 flags |= O_NONBLOCK;
1058
1059 // If this fcntl() fails, we continue but won't
1060 // try to create sparse output. The original
1061 // flags will still be restored if needed (to
1062 // unset O_NONBLOCK) when the file is finished.
1063 if (fcntl(STDOUT_FILENO, F_SETFL, flags) == -1)
1064 return false;
1065
1066 // Disabling O_APPEND succeeded. Mark
1067 // that the flags should be restored
1068 // in io_close_dest(). (This may have already
1069 // been set when enabling O_NONBLOCK.)
1070 restore_stdout_flags = true;
1071
1072 } else if (lseek(STDOUT_FILENO, 0, SEEK_CUR)
1073 != pair->dest_st.st_size) {
1074 // Writing won't start exactly at the end
1075 // of the file. We cannot use sparse output,
1076 // because it would probably corrupt the file.
1077 return false;
1078 }
1079 }
1080
1081 pair->dest_try_sparse = true;
1082 }
1083 #endif
1084
1085 return false;
1086
1087 error:
1088 #ifndef TUKLIB_DOSLIKE
1089 // io_close() closes pair->dir_fd but let's do it here anyway.
1090 if (pair->dir_fd != -1) {
1091 (void)close(pair->dir_fd);
1092 pair->dir_fd = -1;
1093 }
1094 #endif
1095
1096 free(pair->dest_name);
1097 return true;
1098 }
1099
1100
1101 extern bool
io_open_dest(file_pair * pair)1102 io_open_dest(file_pair *pair)
1103 {
1104 signals_block();
1105 const bool ret = io_open_dest_real(pair);
1106 signals_unblock();
1107 return ret;
1108 }
1109
1110
1111 /// \brief Closes destination file of the file_pair structure
1112 ///
1113 /// \param pair File whose dest_fd should be closed
1114 /// \param success If false, the file will be removed from the disk.
1115 ///
1116 /// \return If closing succeeds, false is returned. On error, an error
1117 /// message is printed and true is returned.
1118 static bool
io_close_dest(file_pair * pair,bool success)1119 io_close_dest(file_pair *pair, bool success)
1120 {
1121 #ifndef TUKLIB_DOSLIKE
1122 // If io_open_dest() has disabled O_APPEND, restore it here.
1123 if (restore_stdout_flags) {
1124 assert(pair->dest_fd == STDOUT_FILENO);
1125
1126 restore_stdout_flags = false;
1127
1128 if (fcntl(STDOUT_FILENO, F_SETFL, stdout_flags) == -1) {
1129 message_error(_("Error restoring the O_APPEND flag "
1130 "to standard output: %s"),
1131 strerror(errno));
1132 return true;
1133 }
1134 }
1135 #endif
1136
1137 if (pair->dest_fd == -1 || pair->dest_fd == STDOUT_FILENO)
1138 return false;
1139
1140 #ifndef TUKLIB_DOSLIKE
1141 // dir_fd was only used for syncing the directory.
1142 // Error checking was done when syncing.
1143 if (pair->dir_fd != -1)
1144 (void)close(pair->dir_fd);
1145 #endif
1146
1147 if (close(pair->dest_fd)) {
1148 message_error(_("%s: Closing the file failed: %s"),
1149 tuklib_mask_nonprint(pair->dest_name),
1150 strerror(errno));
1151
1152 // Closing destination file failed, so we cannot trust its
1153 // contents. Get rid of junk:
1154 io_unlink(pair->dest_name, &pair->dest_st);
1155 free(pair->dest_name);
1156 return true;
1157 }
1158
1159 // If the operation using this file wasn't successful, we git rid
1160 // of the junk file.
1161 if (!success)
1162 io_unlink(pair->dest_name, &pair->dest_st);
1163
1164 free(pair->dest_name);
1165
1166 return false;
1167 }
1168
1169
1170 extern void
io_close(file_pair * pair,bool success)1171 io_close(file_pair *pair, bool success)
1172 {
1173 // Take care of sparseness at the end of the output file.
1174 if (success && pair->dest_try_sparse
1175 && pair->dest_pending_sparse > 0) {
1176 // Seek forward one byte less than the size of the pending
1177 // hole, then write one zero-byte. This way the file grows
1178 // to its correct size. An alternative would be to use
1179 // ftruncate() but that isn't portable enough (e.g. it
1180 // doesn't work with FAT on Linux; FAT isn't that important
1181 // since it doesn't support sparse files anyway, but we don't
1182 // want to create corrupt files on it).
1183 if (lseek(pair->dest_fd, pair->dest_pending_sparse - 1,
1184 SEEK_CUR) == -1) {
1185 message_error(_("%s: Seeking failed when trying "
1186 "to create a sparse file: %s"),
1187 tuklib_mask_nonprint(pair->dest_name),
1188 strerror(errno));
1189 success = false;
1190 } else {
1191 const uint8_t zero[1] = { '\0' };
1192 if (io_write_buf(pair, zero, 1))
1193 success = false;
1194 }
1195 }
1196
1197 signals_block();
1198
1199 if (success && pair->dest_fd != -1 && pair->dest_fd != STDOUT_FILENO) {
1200 // Copy the file attributes. This may produce warnings but
1201 // not errors so "success" isn't affected.
1202 io_copy_attrs(pair);
1203
1204 // Synchronize the file and its directory if needed.
1205 if (opt_synchronous)
1206 success = !io_sync_dest(pair);
1207 }
1208
1209 // Close the destination first. If it fails, we must not remove
1210 // the source file!
1211 if (io_close_dest(pair, success))
1212 success = false;
1213
1214 // Close the source file, and unlink it if the operation using this
1215 // file pair was successful and we haven't requested to keep the
1216 // source file.
1217 io_close_src(pair, success);
1218
1219 signals_unblock();
1220
1221 return;
1222 }
1223
1224
1225 extern void
io_fix_src_pos(file_pair * pair,size_t rewind_size)1226 io_fix_src_pos(file_pair *pair, size_t rewind_size)
1227 {
1228 assert(rewind_size <= IO_BUFFER_SIZE);
1229
1230 if (rewind_size > 0) {
1231 // This doesn't need to work on unseekable file descriptors,
1232 // so just ignore possible errors.
1233 (void)lseek(pair->src_fd, -(off_t)(rewind_size), SEEK_CUR);
1234 }
1235
1236 return;
1237 }
1238
1239
1240 extern size_t
io_read(file_pair * pair,io_buf * buf,size_t size)1241 io_read(file_pair *pair, io_buf *buf, size_t size)
1242 {
1243 assert(size <= IO_BUFFER_SIZE);
1244
1245 size_t pos = 0;
1246
1247 while (pos < size) {
1248 const ssize_t amount = read(
1249 pair->src_fd, buf->u8 + pos, size - pos);
1250
1251 if (amount == 0) {
1252 pair->src_eof = true;
1253 break;
1254 }
1255
1256 if (amount == -1) {
1257 if (errno == EINTR) {
1258 if (user_abort)
1259 return SIZE_MAX;
1260
1261 continue;
1262 }
1263
1264 #ifndef TUKLIB_DOSLIKE
1265 if (IS_EAGAIN_OR_EWOULDBLOCK(errno)) {
1266 // Disable the flush-timeout if no input has
1267 // been seen since the previous flush and thus
1268 // there would be nothing to flush after the
1269 // timeout expires (avoids busy waiting).
1270 const int timeout = pair->src_has_seen_input
1271 ? mytime_get_flush_timeout()
1272 : -1;
1273
1274 switch (io_wait(pair, timeout, true)) {
1275 case IO_WAIT_MORE:
1276 continue;
1277
1278 case IO_WAIT_ERROR:
1279 return SIZE_MAX;
1280
1281 case IO_WAIT_TIMEOUT:
1282 pair->flush_needed = true;
1283 return pos;
1284
1285 default:
1286 message_bug();
1287 }
1288 }
1289 #endif
1290
1291 message_error(_("%s: Read error: %s"),
1292 tuklib_mask_nonprint(pair->src_name),
1293 strerror(errno));
1294
1295 return SIZE_MAX;
1296 }
1297
1298 pos += (size_t)(amount);
1299
1300 if (!pair->src_has_seen_input) {
1301 pair->src_has_seen_input = true;
1302 mytime_set_flush_time();
1303 }
1304 }
1305
1306 return pos;
1307 }
1308
1309
1310 extern bool
io_seek_src(file_pair * pair,uint64_t pos)1311 io_seek_src(file_pair *pair, uint64_t pos)
1312 {
1313 // Caller must not attempt to seek past the end of the input file
1314 // (seeking to 100 in a 100-byte file is seeking to the end of
1315 // the file, not past the end of the file, and thus that is allowed).
1316 //
1317 // This also validates that pos can be safely cast to off_t.
1318 if (pos > (uint64_t)(pair->src_st.st_size))
1319 message_bug();
1320
1321 if (lseek(pair->src_fd, (off_t)(pos), SEEK_SET) == -1) {
1322 message_error(_("%s: Error seeking the file: %s"),
1323 tuklib_mask_nonprint(pair->src_name),
1324 strerror(errno));
1325 return true;
1326 }
1327
1328 pair->src_eof = false;
1329
1330 return false;
1331 }
1332
1333
1334 extern bool
io_pread(file_pair * pair,io_buf * buf,size_t size,uint64_t pos)1335 io_pread(file_pair *pair, io_buf *buf, size_t size, uint64_t pos)
1336 {
1337 // Using lseek() and read() is more portable than pread() and
1338 // for us it is as good as real pread().
1339 if (io_seek_src(pair, pos))
1340 return true;
1341
1342 const size_t amount = io_read(pair, buf, size);
1343 if (amount == SIZE_MAX)
1344 return true;
1345
1346 if (amount != size) {
1347 message_error(_("%s: Unexpected end of file"),
1348 tuklib_mask_nonprint(pair->src_name));
1349 return true;
1350 }
1351
1352 return false;
1353 }
1354
1355
1356 static bool
is_sparse(const io_buf * buf)1357 is_sparse(const io_buf *buf)
1358 {
1359 assert(IO_BUFFER_SIZE % sizeof(uint64_t) == 0);
1360
1361 for (size_t i = 0; i < ARRAY_SIZE(buf->u64); ++i)
1362 if (buf->u64[i] != 0)
1363 return false;
1364
1365 return true;
1366 }
1367
1368
1369 static bool
io_write_buf(file_pair * pair,const uint8_t * buf,size_t size)1370 io_write_buf(file_pair *pair, const uint8_t *buf, size_t size)
1371 {
1372 assert(size <= IO_BUFFER_SIZE);
1373
1374 while (size > 0) {
1375 const ssize_t amount = write(pair->dest_fd, buf, size);
1376 if (amount == -1) {
1377 if (errno == EINTR) {
1378 if (user_abort)
1379 return true;
1380
1381 continue;
1382 }
1383
1384 #ifndef TUKLIB_DOSLIKE
1385 if (IS_EAGAIN_OR_EWOULDBLOCK(errno)) {
1386 if (io_wait(pair, -1, false) == IO_WAIT_MORE)
1387 continue;
1388
1389 return true;
1390 }
1391 #endif
1392
1393 #if defined(_WIN32) && !defined(__CYGWIN__)
1394 // On native Windows, broken pipe is reported as
1395 // EINVAL. Don't show an error message in this case.
1396 // Try: xz -dc bigfile.xz | head -n1
1397 if (errno == EINVAL
1398 && pair->dest_fd == STDOUT_FILENO) {
1399 // Emulate SIGPIPE by setting user_abort here.
1400 user_abort = true;
1401 set_exit_status(E_ERROR);
1402 return true;
1403 }
1404 #endif
1405
1406 // Handle broken pipe specially. gzip and bzip2
1407 // don't print anything on SIGPIPE. In addition,
1408 // gzip --quiet uses exit status 2 (warning) on
1409 // broken pipe instead of whatever raise(SIGPIPE)
1410 // would make it return. It is there to hide "Broken
1411 // pipe" message on some old shells (probably old
1412 // GNU bash).
1413 //
1414 // We don't do anything special with --quiet, which
1415 // is what bzip2 does too. If we get SIGPIPE, we
1416 // will handle it like other signals by setting
1417 // user_abort, and get EPIPE here.
1418 if (errno != EPIPE)
1419 message_error(_("%s: Write error: %s"),
1420 tuklib_mask_nonprint(pair->dest_name),
1421 strerror(errno));
1422
1423 return true;
1424 }
1425
1426 buf += (size_t)(amount);
1427 size -= (size_t)(amount);
1428 }
1429
1430 return false;
1431 }
1432
1433
1434 extern bool
io_write(file_pair * pair,const io_buf * buf,size_t size)1435 io_write(file_pair *pair, const io_buf *buf, size_t size)
1436 {
1437 assert(size <= IO_BUFFER_SIZE);
1438
1439 if (pair->dest_try_sparse) {
1440 // Check if the block is sparse (contains only zeros). If it
1441 // sparse, we just store the amount and return. We will take
1442 // care of actually skipping over the hole when we hit the
1443 // next data block or close the file.
1444 //
1445 // Since io_close() requires that dest_pending_sparse > 0
1446 // if the file ends with sparse block, we must also return
1447 // if size == 0 to avoid doing the lseek().
1448 if (size == IO_BUFFER_SIZE) {
1449 // Even if the block was sparse, treat it as non-sparse
1450 // if the pending sparse amount is large compared to
1451 // the size of off_t. In practice this only matters
1452 // on 32-bit systems where off_t isn't always 64 bits.
1453 const off_t pending_max
1454 = (off_t)(1) << (sizeof(off_t) * CHAR_BIT - 2);
1455 if (is_sparse(buf) && pair->dest_pending_sparse
1456 < pending_max) {
1457 pair->dest_pending_sparse += (off_t)(size);
1458 return false;
1459 }
1460 } else if (size == 0) {
1461 return false;
1462 }
1463
1464 // This is not a sparse block. If we have a pending hole,
1465 // skip it now.
1466 if (pair->dest_pending_sparse > 0) {
1467 if (lseek(pair->dest_fd, pair->dest_pending_sparse,
1468 SEEK_CUR) == -1) {
1469 message_error(_("%s: Seeking failed when "
1470 "trying to create a sparse "
1471 "file: %s"),
1472 tuklib_mask_nonprint(
1473 pair->dest_name),
1474 strerror(errno));
1475 return true;
1476 }
1477
1478 pair->dest_pending_sparse = 0;
1479 }
1480 }
1481
1482 return io_write_buf(pair, buf->u8, size);
1483 }
1484