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 #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
io_open_src_real(file_pair * pair)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 *
io_open_src(const char * src_name)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
io_close_src(file_pair * pair,bool success)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
io_open_dest_real(file_pair * pair)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
io_open_dest(file_pair * pair)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
io_close_dest(file_pair * pair,bool success)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
io_close(file_pair * pair,bool success)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
io_fix_src_pos(file_pair * pair,size_t rewind_size)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
io_read(file_pair * pair,io_buf * buf,size_t size)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
io_seek_src(file_pair * pair,uint64_t pos)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
io_pread(file_pair * pair,io_buf * buf,size_t size,uint64_t pos)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
is_sparse(const io_buf * buf)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
io_write_buf(file_pair * pair,const uint8_t * buf,size_t size)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
io_write(file_pair * pair,const io_buf * buf,size_t size)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