15a645f22SBen Gras ///////////////////////////////////////////////////////////////////////////////
25a645f22SBen Gras //
35a645f22SBen Gras /// \file       file_io.c
45a645f22SBen Gras /// \brief      File opening, unlinking, and closing
55a645f22SBen Gras //
65a645f22SBen Gras //  Author:     Lasse Collin
75a645f22SBen Gras //
85a645f22SBen Gras //  This file has been put into the public domain.
95a645f22SBen Gras //  You can do whatever you want with this file.
105a645f22SBen Gras //
115a645f22SBen Gras ///////////////////////////////////////////////////////////////////////////////
125a645f22SBen Gras 
135a645f22SBen Gras #include "private.h"
145a645f22SBen Gras 
155a645f22SBen Gras #include <fcntl.h>
165a645f22SBen Gras 
175a645f22SBen Gras #ifdef TUKLIB_DOSLIKE
185a645f22SBen Gras #	include <io.h>
195a645f22SBen Gras #else
20*0a6a1f1dSLionel Sambuc #	include <poll.h>
215a645f22SBen Gras static bool warn_fchown;
225a645f22SBen Gras #endif
235a645f22SBen Gras 
245a645f22SBen Gras #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMES)
255a645f22SBen Gras #	include <sys/time.h>
265a645f22SBen Gras #elif defined(HAVE_UTIME)
275a645f22SBen Gras #	include <utime.h>
285a645f22SBen Gras #endif
295a645f22SBen Gras 
305a645f22SBen Gras #include "tuklib_open_stdxxx.h"
315a645f22SBen Gras 
325a645f22SBen Gras #ifndef O_BINARY
335a645f22SBen Gras #	define O_BINARY 0
345a645f22SBen Gras #endif
355a645f22SBen Gras 
365a645f22SBen Gras #ifndef O_NOCTTY
375a645f22SBen Gras #	define O_NOCTTY 0
385a645f22SBen Gras #endif
395a645f22SBen Gras 
405a645f22SBen Gras 
41*0a6a1f1dSLionel Sambuc typedef enum {
42*0a6a1f1dSLionel Sambuc 	IO_WAIT_MORE,    // Reading or writing is possible.
43*0a6a1f1dSLionel Sambuc 	IO_WAIT_ERROR,   // Error or user_abort
44*0a6a1f1dSLionel Sambuc 	IO_WAIT_TIMEOUT, // poll() timed out
45*0a6a1f1dSLionel Sambuc } io_wait_ret;
46*0a6a1f1dSLionel Sambuc 
47*0a6a1f1dSLionel Sambuc 
485a645f22SBen Gras /// If true, try to create sparse files when decompressing.
495a645f22SBen Gras static bool try_sparse = true;
505a645f22SBen Gras 
515a645f22SBen Gras #ifndef TUKLIB_DOSLIKE
52*0a6a1f1dSLionel Sambuc /// File status flags of standard input. This is used by io_open_src()
53*0a6a1f1dSLionel Sambuc /// and io_close_src().
54*0a6a1f1dSLionel Sambuc static int stdin_flags;
55*0a6a1f1dSLionel Sambuc static bool restore_stdin_flags = false;
56*0a6a1f1dSLionel Sambuc 
57*0a6a1f1dSLionel Sambuc /// Original file status flags of standard output. This is used by
58*0a6a1f1dSLionel Sambuc /// io_open_dest() and io_close_dest() to save and restore the flags.
59*0a6a1f1dSLionel Sambuc static int stdout_flags;
60*0a6a1f1dSLionel Sambuc static bool restore_stdout_flags = false;
61*0a6a1f1dSLionel Sambuc 
62*0a6a1f1dSLionel Sambuc /// Self-pipe used together with the user_abort variable to avoid
63*0a6a1f1dSLionel Sambuc /// race conditions with signal handling.
64*0a6a1f1dSLionel Sambuc static int user_abort_pipe[2];
655a645f22SBen Gras #endif
665a645f22SBen Gras 
675a645f22SBen Gras 
685a645f22SBen Gras static bool io_write_buf(file_pair *pair, const uint8_t *buf, size_t size);
695a645f22SBen Gras 
705a645f22SBen Gras 
715a645f22SBen Gras extern void
io_init(void)725a645f22SBen Gras io_init(void)
735a645f22SBen Gras {
7411be35a1SLionel Sambuc 	// Make sure that stdin, stdout, and stderr are connected to
755a645f22SBen Gras 	// a valid file descriptor. Exit immediately with exit code ERROR
765a645f22SBen Gras 	// if we cannot make the file descriptors valid. Maybe we should
775a645f22SBen Gras 	// print an error message, but our stderr could be screwed anyway.
785a645f22SBen Gras 	tuklib_open_stdxxx(E_ERROR);
795a645f22SBen Gras 
805a645f22SBen Gras #ifndef TUKLIB_DOSLIKE
815a645f22SBen Gras 	// If fchown() fails setting the owner, we warn about it only if
825a645f22SBen Gras 	// we are root.
835a645f22SBen Gras 	warn_fchown = geteuid() == 0;
84*0a6a1f1dSLionel Sambuc 
85*0a6a1f1dSLionel Sambuc 	// Create a pipe for the self-pipe trick. If pipe2() is available,
86*0a6a1f1dSLionel Sambuc 	// we can avoid the fcntl() calls.
87*0a6a1f1dSLionel Sambuc #	ifdef HAVE_PIPE2
88*0a6a1f1dSLionel Sambuc 	if (pipe2(user_abort_pipe, O_NONBLOCK))
89*0a6a1f1dSLionel Sambuc 		message_fatal(_("Error creating a pipe: %s"),
90*0a6a1f1dSLionel Sambuc 				strerror(errno));
91*0a6a1f1dSLionel Sambuc #	else
92*0a6a1f1dSLionel Sambuc 	if (pipe(user_abort_pipe))
93*0a6a1f1dSLionel Sambuc 		message_fatal(_("Error creating a pipe: %s"),
94*0a6a1f1dSLionel Sambuc 				strerror(errno));
95*0a6a1f1dSLionel Sambuc 
96*0a6a1f1dSLionel Sambuc 	// Make both ends of the pipe non-blocking.
97*0a6a1f1dSLionel Sambuc 	for (unsigned i = 0; i < 2; ++i) {
98*0a6a1f1dSLionel Sambuc 		int flags = fcntl(user_abort_pipe[i], F_GETFL);
99*0a6a1f1dSLionel Sambuc 		if (flags == -1 || fcntl(user_abort_pipe[i], F_SETFL,
100*0a6a1f1dSLionel Sambuc 				flags | O_NONBLOCK) == -1)
101*0a6a1f1dSLionel Sambuc 			message_fatal(_("Error creating a pipe: %s"),
102*0a6a1f1dSLionel Sambuc 					strerror(errno));
103*0a6a1f1dSLionel Sambuc 	}
104*0a6a1f1dSLionel Sambuc #	endif
1055a645f22SBen Gras #endif
1065a645f22SBen Gras 
1075a645f22SBen Gras #ifdef __DJGPP__
1085a645f22SBen Gras 	// Avoid doing useless things when statting files.
1095a645f22SBen Gras 	// This isn't important but doesn't hurt.
110*0a6a1f1dSLionel Sambuc 	_djstat_flags = _STAT_EXEC_EXT | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
1115a645f22SBen Gras #endif
1125a645f22SBen Gras 
1135a645f22SBen Gras 	return;
1145a645f22SBen Gras }
1155a645f22SBen Gras 
1165a645f22SBen Gras 
117*0a6a1f1dSLionel Sambuc #ifndef TUKLIB_DOSLIKE
118*0a6a1f1dSLionel Sambuc extern void
io_write_to_user_abort_pipe(void)119*0a6a1f1dSLionel Sambuc io_write_to_user_abort_pipe(void)
120*0a6a1f1dSLionel Sambuc {
121*0a6a1f1dSLionel Sambuc 	// If the write() fails, it's probably due to the pipe being full.
122*0a6a1f1dSLionel Sambuc 	// Failing in that case is fine. If the reason is something else,
123*0a6a1f1dSLionel Sambuc 	// there's not much we can do since this is called in a signal
124*0a6a1f1dSLionel Sambuc 	// handler. So ignore the errors and try to avoid warnings with
125*0a6a1f1dSLionel Sambuc 	// GCC and glibc when _FORTIFY_SOURCE=2 is used.
126*0a6a1f1dSLionel Sambuc 	uint8_t b = '\0';
127*0a6a1f1dSLionel Sambuc 	const int ret = write(user_abort_pipe[1], &b, 1);
128*0a6a1f1dSLionel Sambuc 	(void)ret;
129*0a6a1f1dSLionel Sambuc 	return;
130*0a6a1f1dSLionel Sambuc }
131*0a6a1f1dSLionel Sambuc #endif
132*0a6a1f1dSLionel Sambuc 
133*0a6a1f1dSLionel Sambuc 
1345a645f22SBen Gras extern void
io_no_sparse(void)1355a645f22SBen Gras io_no_sparse(void)
1365a645f22SBen Gras {
1375a645f22SBen Gras 	try_sparse = false;
1385a645f22SBen Gras 	return;
1395a645f22SBen Gras }
1405a645f22SBen Gras 
1415a645f22SBen Gras 
142*0a6a1f1dSLionel Sambuc #ifndef TUKLIB_DOSLIKE
143*0a6a1f1dSLionel Sambuc /// \brief      Waits for input or output to become available or for a signal
144*0a6a1f1dSLionel Sambuc ///
145*0a6a1f1dSLionel Sambuc /// This uses the self-pipe trick to avoid a race condition that can occur
146*0a6a1f1dSLionel Sambuc /// if a signal is caught after user_abort has been checked but before e.g.
147*0a6a1f1dSLionel Sambuc /// read() has been called. In that situation read() could block unless
148*0a6a1f1dSLionel Sambuc /// non-blocking I/O is used. With non-blocking I/O something like select()
149*0a6a1f1dSLionel Sambuc /// or poll() is needed to avoid a busy-wait loop, and the same race condition
150*0a6a1f1dSLionel Sambuc /// pops up again. There are pselect() (POSIX-1.2001) and ppoll() (not in
151*0a6a1f1dSLionel Sambuc /// POSIX) but neither is portable enough in 2013. The self-pipe trick is
152*0a6a1f1dSLionel Sambuc /// old and very portable.
153*0a6a1f1dSLionel Sambuc static io_wait_ret
io_wait(file_pair * pair,int timeout,bool is_reading)154*0a6a1f1dSLionel Sambuc io_wait(file_pair *pair, int timeout, bool is_reading)
155*0a6a1f1dSLionel Sambuc {
156*0a6a1f1dSLionel Sambuc 	struct pollfd pfd[2];
157*0a6a1f1dSLionel Sambuc 
158*0a6a1f1dSLionel Sambuc 	if (is_reading) {
159*0a6a1f1dSLionel Sambuc 		pfd[0].fd = pair->src_fd;
160*0a6a1f1dSLionel Sambuc 		pfd[0].events = POLLIN;
161*0a6a1f1dSLionel Sambuc 	} else {
162*0a6a1f1dSLionel Sambuc 		pfd[0].fd = pair->dest_fd;
163*0a6a1f1dSLionel Sambuc 		pfd[0].events = POLLOUT;
164*0a6a1f1dSLionel Sambuc 	}
165*0a6a1f1dSLionel Sambuc 
166*0a6a1f1dSLionel Sambuc 	pfd[1].fd = user_abort_pipe[0];
167*0a6a1f1dSLionel Sambuc 	pfd[1].events = POLLIN;
168*0a6a1f1dSLionel Sambuc 
169*0a6a1f1dSLionel Sambuc 	while (true) {
170*0a6a1f1dSLionel Sambuc 		const int ret = poll(pfd, 2, timeout);
171*0a6a1f1dSLionel Sambuc 
172*0a6a1f1dSLionel Sambuc 		if (user_abort)
173*0a6a1f1dSLionel Sambuc 			return IO_WAIT_ERROR;
174*0a6a1f1dSLionel Sambuc 
175*0a6a1f1dSLionel Sambuc 		if (ret == -1) {
176*0a6a1f1dSLionel Sambuc 			if (errno == EINTR || errno == EAGAIN)
177*0a6a1f1dSLionel Sambuc 				continue;
178*0a6a1f1dSLionel Sambuc 
179*0a6a1f1dSLionel Sambuc 			message_error(_("%s: poll() failed: %s"),
180*0a6a1f1dSLionel Sambuc 					is_reading ? pair->src_name
181*0a6a1f1dSLionel Sambuc 						: pair->dest_name,
182*0a6a1f1dSLionel Sambuc 					strerror(errno));
183*0a6a1f1dSLionel Sambuc 			return IO_WAIT_ERROR;
184*0a6a1f1dSLionel Sambuc 		}
185*0a6a1f1dSLionel Sambuc 
186*0a6a1f1dSLionel Sambuc 		if (ret == 0) {
187*0a6a1f1dSLionel Sambuc 			assert(opt_flush_timeout != 0);
188*0a6a1f1dSLionel Sambuc 			flush_needed = true;
189*0a6a1f1dSLionel Sambuc 			return IO_WAIT_TIMEOUT;
190*0a6a1f1dSLionel Sambuc 		}
191*0a6a1f1dSLionel Sambuc 
192*0a6a1f1dSLionel Sambuc 		if (pfd[0].revents != 0)
193*0a6a1f1dSLionel Sambuc 			return IO_WAIT_MORE;
194*0a6a1f1dSLionel Sambuc 	}
195*0a6a1f1dSLionel Sambuc }
196*0a6a1f1dSLionel Sambuc #endif
197*0a6a1f1dSLionel Sambuc 
198*0a6a1f1dSLionel Sambuc 
1995a645f22SBen Gras /// \brief      Unlink a file
2005a645f22SBen Gras ///
2015a645f22SBen Gras /// This tries to verify that the file being unlinked really is the file that
2025a645f22SBen Gras /// we want to unlink by verifying device and inode numbers. There's still
2035a645f22SBen Gras /// a small unavoidable race, but this is much better than nothing (the file
2045a645f22SBen Gras /// could have been moved/replaced even hours earlier).
2055a645f22SBen Gras static void
io_unlink(const char * name,const struct stat * known_st)2065a645f22SBen Gras io_unlink(const char *name, const struct stat *known_st)
2075a645f22SBen Gras {
2085a645f22SBen Gras #if defined(TUKLIB_DOSLIKE)
2095a645f22SBen Gras 	// On DOS-like systems, st_ino is meaningless, so don't bother
2105a645f22SBen Gras 	// testing it. Just silence a compiler warning.
2115a645f22SBen Gras 	(void)known_st;
2125a645f22SBen Gras #else
2135a645f22SBen Gras 	struct stat new_st;
2145a645f22SBen Gras 
2155a645f22SBen Gras 	// If --force was used, use stat() instead of lstat(). This way
2165a645f22SBen Gras 	// (de)compressing symlinks works correctly. However, it also means
2175a645f22SBen Gras 	// that xz cannot detect if a regular file foo is renamed to bar
2185a645f22SBen Gras 	// and then a symlink foo -> bar is created. Because of stat()
2195a645f22SBen Gras 	// instead of lstat(), xz will think that foo hasn't been replaced
2205a645f22SBen Gras 	// with another file. Thus, xz will remove foo even though it no
2215a645f22SBen Gras 	// longer is the same file that xz used when it started compressing.
2225a645f22SBen Gras 	// Probably it's not too bad though, so this doesn't need a more
2235a645f22SBen Gras 	// complex fix.
2245a645f22SBen Gras 	const int stat_ret = opt_force
2255a645f22SBen Gras 			? stat(name, &new_st) : lstat(name, &new_st);
2265a645f22SBen Gras 
2275a645f22SBen Gras 	if (stat_ret
2285a645f22SBen Gras #	ifdef __VMS
2295a645f22SBen Gras 			// st_ino is an array, and we don't want to
2305a645f22SBen Gras 			// compare st_dev at all.
2315a645f22SBen Gras 			|| memcmp(&new_st.st_ino, &known_st->st_ino,
2325a645f22SBen Gras 				sizeof(new_st.st_ino)) != 0
2335a645f22SBen Gras #	else
2345a645f22SBen Gras 			// Typical POSIX-like system
2355a645f22SBen Gras 			|| new_st.st_dev != known_st->st_dev
2365a645f22SBen Gras 			|| new_st.st_ino != known_st->st_ino
2375a645f22SBen Gras #	endif
2385a645f22SBen Gras 			)
2395a645f22SBen Gras 		// TRANSLATORS: When compression or decompression finishes,
2405a645f22SBen Gras 		// and xz is going to remove the source file, xz first checks
2415a645f22SBen Gras 		// if the source file still exists, and if it does, does its
2425a645f22SBen Gras 		// device and inode numbers match what xz saw when it opened
2435a645f22SBen Gras 		// the source file. If these checks fail, this message is
2445a645f22SBen Gras 		// shown, %s being the filename, and the file is not deleted.
2455a645f22SBen Gras 		// The check for device and inode numbers is there, because
2465a645f22SBen Gras 		// it is possible that the user has put a new file in place
2475a645f22SBen Gras 		// of the original file, and in that case it obviously
2485a645f22SBen Gras 		// shouldn't be removed.
2495a645f22SBen Gras 		message_error(_("%s: File seems to have been moved, "
2505a645f22SBen Gras 				"not removing"), name);
2515a645f22SBen Gras 	else
2525a645f22SBen Gras #endif
2535a645f22SBen Gras 		// There's a race condition between lstat() and unlink()
2545a645f22SBen Gras 		// but at least we have tried to avoid removing wrong file.
2555a645f22SBen Gras 		if (unlink(name))
2565a645f22SBen Gras 			message_error(_("%s: Cannot remove: %s"),
2575a645f22SBen Gras 					name, strerror(errno));
2585a645f22SBen Gras 
2595a645f22SBen Gras 	return;
2605a645f22SBen Gras }
2615a645f22SBen Gras 
2625a645f22SBen Gras 
2635a645f22SBen Gras /// \brief      Copies owner/group and permissions
2645a645f22SBen Gras ///
2655a645f22SBen Gras /// \todo       ACL and EA support
2665a645f22SBen Gras ///
2675a645f22SBen Gras static void
io_copy_attrs(const file_pair * pair)2685a645f22SBen Gras io_copy_attrs(const file_pair *pair)
2695a645f22SBen Gras {
2705a645f22SBen Gras 	// Skip chown and chmod on Windows.
2715a645f22SBen Gras #ifndef TUKLIB_DOSLIKE
2725a645f22SBen Gras 	// This function is more tricky than you may think at first.
2735a645f22SBen Gras 	// Blindly copying permissions may permit users to access the
2745a645f22SBen Gras 	// destination file who didn't have permission to access the
2755a645f22SBen Gras 	// source file.
2765a645f22SBen Gras 
2775a645f22SBen Gras 	// Try changing the owner of the file. If we aren't root or the owner
2785a645f22SBen Gras 	// isn't already us, fchown() probably doesn't succeed. We warn
2795a645f22SBen Gras 	// about failing fchown() only if we are root.
2805a645f22SBen Gras 	if (fchown(pair->dest_fd, pair->src_st.st_uid, -1) && warn_fchown)
2815a645f22SBen Gras 		message_warning(_("%s: Cannot set the file owner: %s"),
2825a645f22SBen Gras 				pair->dest_name, strerror(errno));
2835a645f22SBen Gras 
2845a645f22SBen Gras 	mode_t mode;
2855a645f22SBen Gras 
2865a645f22SBen Gras 	if (fchown(pair->dest_fd, -1, pair->src_st.st_gid)) {
2875a645f22SBen Gras 		message_warning(_("%s: Cannot set the file group: %s"),
2885a645f22SBen Gras 				pair->dest_name, strerror(errno));
2895a645f22SBen Gras 		// We can still safely copy some additional permissions:
2905a645f22SBen Gras 		// `group' must be at least as strict as `other' and
2915a645f22SBen Gras 		// also vice versa.
2925a645f22SBen Gras 		//
2935a645f22SBen Gras 		// NOTE: After this, the owner of the source file may
2945a645f22SBen Gras 		// get additional permissions. This shouldn't be too bad,
2955a645f22SBen Gras 		// because the owner would have had permission to chmod
2965a645f22SBen Gras 		// the original file anyway.
2975a645f22SBen Gras 		mode = ((pair->src_st.st_mode & 0070) >> 3)
2985a645f22SBen Gras 				& (pair->src_st.st_mode & 0007);
2995a645f22SBen Gras 		mode = (pair->src_st.st_mode & 0700) | (mode << 3) | mode;
3005a645f22SBen Gras 	} else {
3015a645f22SBen Gras 		// Drop the setuid, setgid, and sticky bits.
3025a645f22SBen Gras 		mode = pair->src_st.st_mode & 0777;
3035a645f22SBen Gras 	}
3045a645f22SBen Gras 
3055a645f22SBen Gras 	if (fchmod(pair->dest_fd, mode))
3065a645f22SBen Gras 		message_warning(_("%s: Cannot set the file permissions: %s"),
3075a645f22SBen Gras 				pair->dest_name, strerror(errno));
3085a645f22SBen Gras #endif
3095a645f22SBen Gras 
3105a645f22SBen Gras 	// Copy the timestamps. We have several possible ways to do this, of
3115a645f22SBen Gras 	// which some are better in both security and precision.
3125a645f22SBen Gras 	//
3135a645f22SBen Gras 	// First, get the nanosecond part of the timestamps. As of writing,
3145a645f22SBen Gras 	// it's not standardized by POSIX, and there are several names for
3155a645f22SBen Gras 	// the same thing in struct stat.
3165a645f22SBen Gras 	long atime_nsec;
3175a645f22SBen Gras 	long mtime_nsec;
3185a645f22SBen Gras 
3195a645f22SBen Gras #	if defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
3205a645f22SBen Gras 	// GNU and Solaris
3215a645f22SBen Gras 	atime_nsec = pair->src_st.st_atim.tv_nsec;
3225a645f22SBen Gras 	mtime_nsec = pair->src_st.st_mtim.tv_nsec;
3235a645f22SBen Gras 
3245a645f22SBen Gras #	elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
3255a645f22SBen Gras 	// BSD
3265a645f22SBen Gras 	atime_nsec = pair->src_st.st_atimespec.tv_nsec;
3275a645f22SBen Gras 	mtime_nsec = pair->src_st.st_mtimespec.tv_nsec;
3285a645f22SBen Gras 
3295a645f22SBen Gras #	elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
3305a645f22SBen Gras 	// GNU and BSD without extensions
3315a645f22SBen Gras 	atime_nsec = pair->src_st.st_atimensec;
3325a645f22SBen Gras 	mtime_nsec = pair->src_st.st_mtimensec;
3335a645f22SBen Gras 
3345a645f22SBen Gras #	elif defined(HAVE_STRUCT_STAT_ST_UATIME)
3355a645f22SBen Gras 	// Tru64
3365a645f22SBen Gras 	atime_nsec = pair->src_st.st_uatime * 1000;
3375a645f22SBen Gras 	mtime_nsec = pair->src_st.st_umtime * 1000;
3385a645f22SBen Gras 
3395a645f22SBen Gras #	elif defined(HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC)
3405a645f22SBen Gras 	// UnixWare
3415a645f22SBen Gras 	atime_nsec = pair->src_st.st_atim.st__tim.tv_nsec;
3425a645f22SBen Gras 	mtime_nsec = pair->src_st.st_mtim.st__tim.tv_nsec;
3435a645f22SBen Gras 
3445a645f22SBen Gras #	else
3455a645f22SBen Gras 	// Safe fallback
3465a645f22SBen Gras 	atime_nsec = 0;
3475a645f22SBen Gras 	mtime_nsec = 0;
3485a645f22SBen Gras #	endif
3495a645f22SBen Gras 
3505a645f22SBen Gras 	// Construct a structure to hold the timestamps and call appropriate
3515a645f22SBen Gras 	// function to set the timestamps.
3525a645f22SBen Gras #if defined(HAVE_FUTIMENS)
3535a645f22SBen Gras 	// Use nanosecond precision.
3545a645f22SBen Gras 	struct timespec tv[2];
3555a645f22SBen Gras 	tv[0].tv_sec = pair->src_st.st_atime;
3565a645f22SBen Gras 	tv[0].tv_nsec = atime_nsec;
3575a645f22SBen Gras 	tv[1].tv_sec = pair->src_st.st_mtime;
3585a645f22SBen Gras 	tv[1].tv_nsec = mtime_nsec;
3595a645f22SBen Gras 
3605a645f22SBen Gras 	(void)futimens(pair->dest_fd, tv);
3615a645f22SBen Gras 
3625a645f22SBen Gras #elif defined(HAVE_FUTIMES) || defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMES)
3635a645f22SBen Gras 	// Use microsecond precision.
3645a645f22SBen Gras 	struct timeval tv[2];
3655a645f22SBen Gras 	tv[0].tv_sec = pair->src_st.st_atime;
3665a645f22SBen Gras 	tv[0].tv_usec = atime_nsec / 1000;
3675a645f22SBen Gras 	tv[1].tv_sec = pair->src_st.st_mtime;
3685a645f22SBen Gras 	tv[1].tv_usec = mtime_nsec / 1000;
3695a645f22SBen Gras 
3705a645f22SBen Gras #	if defined(HAVE_FUTIMES)
3715a645f22SBen Gras 	(void)futimes(pair->dest_fd, tv);
3725a645f22SBen Gras #	elif defined(HAVE_FUTIMESAT)
3735a645f22SBen Gras 	(void)futimesat(pair->dest_fd, NULL, tv);
3745a645f22SBen Gras #	else
3755a645f22SBen Gras 	// Argh, no function to use a file descriptor to set the timestamp.
3765a645f22SBen Gras 	(void)utimes(pair->dest_name, tv);
3775a645f22SBen Gras #	endif
3785a645f22SBen Gras 
3795a645f22SBen Gras #elif defined(HAVE_UTIME)
3805a645f22SBen Gras 	// Use one-second precision. utime() doesn't support using file
3815a645f22SBen Gras 	// descriptor either. Some systems have broken utime() prototype
3825a645f22SBen Gras 	// so don't make this const.
3835a645f22SBen Gras 	struct utimbuf buf = {
3845a645f22SBen Gras 		.actime = pair->src_st.st_atime,
3855a645f22SBen Gras 		.modtime = pair->src_st.st_mtime,
3865a645f22SBen Gras 	};
3875a645f22SBen Gras 
3885a645f22SBen Gras 	// Avoid warnings.
3895a645f22SBen Gras 	(void)atime_nsec;
3905a645f22SBen Gras 	(void)mtime_nsec;
3915a645f22SBen Gras 
3925a645f22SBen Gras 	(void)utime(pair->dest_name, &buf);
3935a645f22SBen Gras #endif
3945a645f22SBen Gras 
3955a645f22SBen Gras 	return;
3965a645f22SBen Gras }
3975a645f22SBen Gras 
3985a645f22SBen Gras 
3995a645f22SBen Gras /// Opens the source file. Returns false on success, true on error.
4005a645f22SBen Gras static bool
io_open_src_real(file_pair * pair)4015a645f22SBen Gras io_open_src_real(file_pair *pair)
4025a645f22SBen Gras {
4035a645f22SBen Gras 	// There's nothing to open when reading from stdin.
4045a645f22SBen Gras 	if (pair->src_name == stdin_filename) {
4055a645f22SBen Gras 		pair->src_fd = STDIN_FILENO;
4065a645f22SBen Gras #ifdef TUKLIB_DOSLIKE
4075a645f22SBen Gras 		setmode(STDIN_FILENO, O_BINARY);
408*0a6a1f1dSLionel Sambuc #else
409*0a6a1f1dSLionel Sambuc 		// Try to set stdin to non-blocking mode. It won't work
410*0a6a1f1dSLionel Sambuc 		// e.g. on OpenBSD if stdout is e.g. /dev/null. In such
411*0a6a1f1dSLionel Sambuc 		// case we proceed as if stdin were non-blocking anyway
412*0a6a1f1dSLionel Sambuc 		// (in case of /dev/null it will be in practice). The
413*0a6a1f1dSLionel Sambuc 		// same applies to stdout in io_open_dest_real().
414*0a6a1f1dSLionel Sambuc 		stdin_flags = fcntl(STDIN_FILENO, F_GETFL);
415*0a6a1f1dSLionel Sambuc 		if (stdin_flags == -1) {
416*0a6a1f1dSLionel Sambuc 			message_error(_("Error getting the file status flags "
417*0a6a1f1dSLionel Sambuc 					"from standard input: %s"),
418*0a6a1f1dSLionel Sambuc 					strerror(errno));
419*0a6a1f1dSLionel Sambuc 			return true;
420*0a6a1f1dSLionel Sambuc 		}
421*0a6a1f1dSLionel Sambuc 
422*0a6a1f1dSLionel Sambuc 		if ((stdin_flags & O_NONBLOCK) == 0
423*0a6a1f1dSLionel Sambuc 				&& fcntl(STDIN_FILENO, F_SETFL,
424*0a6a1f1dSLionel Sambuc 					stdin_flags | O_NONBLOCK) != -1)
425*0a6a1f1dSLionel Sambuc 			restore_stdin_flags = true;
426*0a6a1f1dSLionel Sambuc #endif
427*0a6a1f1dSLionel Sambuc #ifdef HAVE_POSIX_FADVISE
428*0a6a1f1dSLionel Sambuc 		// It will fail if stdin is a pipe and that's fine.
429*0a6a1f1dSLionel Sambuc 		(void)posix_fadvise(STDIN_FILENO, 0, 0, POSIX_FADV_SEQUENTIAL);
4305a645f22SBen Gras #endif
4315a645f22SBen Gras 		return false;
4325a645f22SBen Gras 	}
4335a645f22SBen Gras 
4345a645f22SBen Gras 	// Symlinks are not followed unless writing to stdout or --force
4355a645f22SBen Gras 	// was used.
4365a645f22SBen Gras 	const bool follow_symlinks = opt_stdout || opt_force;
4375a645f22SBen Gras 
4385a645f22SBen Gras 	// We accept only regular files if we are writing the output
4395a645f22SBen Gras 	// to disk too. bzip2 allows overriding this with --force but
4405a645f22SBen Gras 	// gzip and xz don't.
4415a645f22SBen Gras 	const bool reg_files_only = !opt_stdout;
4425a645f22SBen Gras 
4435a645f22SBen Gras 	// Flags for open()
4445a645f22SBen Gras 	int flags = O_RDONLY | O_BINARY | O_NOCTTY;
4455a645f22SBen Gras 
4465a645f22SBen Gras #ifndef TUKLIB_DOSLIKE
447*0a6a1f1dSLionel Sambuc 	// Use non-blocking I/O:
448*0a6a1f1dSLionel Sambuc 	//   - It prevents blocking when opening FIFOs and some other
449*0a6a1f1dSLionel Sambuc 	//     special files, which is good if we want to accept only
450*0a6a1f1dSLionel Sambuc 	//     regular files.
451*0a6a1f1dSLionel Sambuc 	//   - It can help avoiding some race conditions with signal handling.
4525a645f22SBen Gras 	flags |= O_NONBLOCK;
4535a645f22SBen Gras #endif
4545a645f22SBen Gras 
4555a645f22SBen Gras #if defined(O_NOFOLLOW)
4565a645f22SBen Gras 	if (!follow_symlinks)
4575a645f22SBen Gras 		flags |= O_NOFOLLOW;
4585a645f22SBen Gras #elif !defined(TUKLIB_DOSLIKE)
4595a645f22SBen Gras 	// Some POSIX-like systems lack O_NOFOLLOW (it's not required
4605a645f22SBen Gras 	// by POSIX). Check for symlinks with a separate lstat() on
4615a645f22SBen Gras 	// these systems.
4625a645f22SBen Gras 	if (!follow_symlinks) {
4635a645f22SBen Gras 		struct stat st;
4645a645f22SBen Gras 		if (lstat(pair->src_name, &st)) {
4655a645f22SBen Gras 			message_error("%s: %s", pair->src_name,
4665a645f22SBen Gras 					strerror(errno));
4675a645f22SBen Gras 			return true;
4685a645f22SBen Gras 
4695a645f22SBen Gras 		} else if (S_ISLNK(st.st_mode)) {
4705a645f22SBen Gras 			message_warning(_("%s: Is a symbolic link, "
4715a645f22SBen Gras 					"skipping"), pair->src_name);
4725a645f22SBen Gras 			return true;
4735a645f22SBen Gras 		}
4745a645f22SBen Gras 	}
4755a645f22SBen Gras #else
4765a645f22SBen Gras 	// Avoid warnings.
4775a645f22SBen Gras 	(void)follow_symlinks;
4785a645f22SBen Gras #endif
4795a645f22SBen Gras 
480*0a6a1f1dSLionel Sambuc 	// Try to open the file. Signals have been blocked so EINTR shouldn't
481*0a6a1f1dSLionel Sambuc 	// be possible.
4825a645f22SBen Gras 	pair->src_fd = open(pair->src_name, flags);
4835a645f22SBen Gras 
4845a645f22SBen Gras 	if (pair->src_fd == -1) {
485*0a6a1f1dSLionel Sambuc 		// Signals (that have a signal handler) have been blocked.
486*0a6a1f1dSLionel Sambuc 		assert(errno != EINTR);
4875a645f22SBen Gras 
4885a645f22SBen Gras #ifdef O_NOFOLLOW
4895a645f22SBen Gras 		// Give an understandable error message if the reason
4905a645f22SBen Gras 		// for failing was that the file was a symbolic link.
4915a645f22SBen Gras 		//
4925a645f22SBen Gras 		// Note that at least Linux, OpenBSD, Solaris, and Darwin
4935a645f22SBen Gras 		// use ELOOP to indicate that O_NOFOLLOW was the reason
4945a645f22SBen Gras 		// that open() failed. Because there may be
4955a645f22SBen Gras 		// directories in the pathname, ELOOP may occur also
4965a645f22SBen Gras 		// because of a symlink loop in the directory part.
4975a645f22SBen Gras 		// So ELOOP doesn't tell us what actually went wrong,
4985a645f22SBen Gras 		// and this stupidity went into POSIX-1.2008 too.
4995a645f22SBen Gras 		//
5005a645f22SBen Gras 		// FreeBSD associates EMLINK with O_NOFOLLOW and
5015a645f22SBen Gras 		// Tru64 uses ENOTSUP. We use these directly here
5025a645f22SBen Gras 		// and skip the lstat() call and the associated race.
5035a645f22SBen Gras 		// I want to hear if there are other kernels that
5045a645f22SBen Gras 		// fail with something else than ELOOP with O_NOFOLLOW.
5055a645f22SBen Gras 		bool was_symlink = false;
5065a645f22SBen Gras 
5075a645f22SBen Gras #	if defined(__FreeBSD__) || defined(__DragonFly__)
5085a645f22SBen Gras 		if (errno == EMLINK)
5095a645f22SBen Gras 			was_symlink = true;
5105a645f22SBen Gras 
5115a645f22SBen Gras #	elif defined(__digital__) && defined(__unix__)
5125a645f22SBen Gras 		if (errno == ENOTSUP)
5135a645f22SBen Gras 			was_symlink = true;
5145a645f22SBen Gras 
5155a645f22SBen Gras #	elif defined(__NetBSD__)
5165a645f22SBen Gras 		if (errno == EFTYPE)
5175a645f22SBen Gras 			was_symlink = true;
5185a645f22SBen Gras 
5195a645f22SBen Gras #	else
5205a645f22SBen Gras 		if (errno == ELOOP && !follow_symlinks) {
5215a645f22SBen Gras 			const int saved_errno = errno;
5225a645f22SBen Gras 			struct stat st;
5235a645f22SBen Gras 			if (lstat(pair->src_name, &st) == 0
5245a645f22SBen Gras 					&& S_ISLNK(st.st_mode))
5255a645f22SBen Gras 				was_symlink = true;
5265a645f22SBen Gras 
5275a645f22SBen Gras 			errno = saved_errno;
5285a645f22SBen Gras 		}
5295a645f22SBen Gras #	endif
5305a645f22SBen Gras 
5315a645f22SBen Gras 		if (was_symlink)
5325a645f22SBen Gras 			message_warning(_("%s: Is a symbolic link, "
5335a645f22SBen Gras 					"skipping"), pair->src_name);
5345a645f22SBen Gras 		else
5355a645f22SBen Gras #endif
5365a645f22SBen Gras 			// Something else than O_NOFOLLOW failing
5375a645f22SBen Gras 			// (assuming that the race conditions didn't
5385a645f22SBen Gras 			// confuse us).
5395a645f22SBen Gras 			message_error("%s: %s", pair->src_name,
5405a645f22SBen Gras 					strerror(errno));
5415a645f22SBen Gras 
5425a645f22SBen Gras 		return true;
5435a645f22SBen Gras 	}
5445a645f22SBen Gras 
5455a645f22SBen Gras 	// Stat the source file. We need the result also when we copy
5465a645f22SBen Gras 	// the permissions, and when unlinking.
547*0a6a1f1dSLionel Sambuc 	//
548*0a6a1f1dSLionel Sambuc 	// NOTE: Use stat() instead of fstat() with DJGPP, because
549*0a6a1f1dSLionel Sambuc 	// then we have a better chance to get st_ino value that can
550*0a6a1f1dSLionel Sambuc 	// be used in io_open_dest_real() to prevent overwriting the
551*0a6a1f1dSLionel Sambuc 	// source file.
552*0a6a1f1dSLionel Sambuc #ifdef __DJGPP__
553*0a6a1f1dSLionel Sambuc 	if (stat(pair->src_name, &pair->src_st))
554*0a6a1f1dSLionel Sambuc 		goto error_msg;
555*0a6a1f1dSLionel Sambuc #else
5565a645f22SBen Gras 	if (fstat(pair->src_fd, &pair->src_st))
5575a645f22SBen Gras 		goto error_msg;
558*0a6a1f1dSLionel Sambuc #endif
5595a645f22SBen Gras 
5605a645f22SBen Gras 	if (S_ISDIR(pair->src_st.st_mode)) {
5615a645f22SBen Gras 		message_warning(_("%s: Is a directory, skipping"),
5625a645f22SBen Gras 				pair->src_name);
5635a645f22SBen Gras 		goto error;
5645a645f22SBen Gras 	}
5655a645f22SBen Gras 
56611be35a1SLionel Sambuc 	if (reg_files_only && !S_ISREG(pair->src_st.st_mode)) {
56711be35a1SLionel Sambuc 		message_warning(_("%s: Not a regular file, skipping"),
56811be35a1SLionel Sambuc 				pair->src_name);
5695a645f22SBen Gras 		goto error;
5705a645f22SBen Gras 	}
5715a645f22SBen Gras 
5725a645f22SBen Gras #ifndef TUKLIB_DOSLIKE
57311be35a1SLionel Sambuc 	if (reg_files_only && !opt_force) {
5745a645f22SBen Gras 		if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) {
5755a645f22SBen Gras 			// gzip rejects setuid and setgid files even
5765a645f22SBen Gras 			// when --force was used. bzip2 doesn't check
5775a645f22SBen Gras 			// for them, but calls fchown() after fchmod(),
5785a645f22SBen Gras 			// and many systems automatically drop setuid
5795a645f22SBen Gras 			// and setgid bits there.
5805a645f22SBen Gras 			//
5815a645f22SBen Gras 			// We accept setuid and setgid files if
5825a645f22SBen Gras 			// --force was used. We drop these bits
5835a645f22SBen Gras 			// explicitly in io_copy_attr().
5845a645f22SBen Gras 			message_warning(_("%s: File has setuid or "
5855a645f22SBen Gras 					"setgid bit set, skipping"),
5865a645f22SBen Gras 					pair->src_name);
5875a645f22SBen Gras 			goto error;
5885a645f22SBen Gras 		}
5895a645f22SBen Gras 
5905a645f22SBen Gras 		if (pair->src_st.st_mode & S_ISVTX) {
5915a645f22SBen Gras 			message_warning(_("%s: File has sticky bit "
5925a645f22SBen Gras 					"set, skipping"),
5935a645f22SBen Gras 					pair->src_name);
5945a645f22SBen Gras 			goto error;
5955a645f22SBen Gras 		}
5965a645f22SBen Gras 
5975a645f22SBen Gras 		if (pair->src_st.st_nlink > 1) {
5985a645f22SBen Gras 			message_warning(_("%s: Input file has more "
5995a645f22SBen Gras 					"than one hard link, "
6005a645f22SBen Gras 					"skipping"), pair->src_name);
6015a645f22SBen Gras 			goto error;
6025a645f22SBen Gras 		}
6035a645f22SBen Gras 	}
604*0a6a1f1dSLionel Sambuc 
605*0a6a1f1dSLionel Sambuc 	// If it is something else than a regular file, wait until
606*0a6a1f1dSLionel Sambuc 	// there is input available. This way reading from FIFOs
607*0a6a1f1dSLionel Sambuc 	// will work when open() is used with O_NONBLOCK.
608*0a6a1f1dSLionel Sambuc 	if (!S_ISREG(pair->src_st.st_mode)) {
609*0a6a1f1dSLionel Sambuc 		signals_unblock();
610*0a6a1f1dSLionel Sambuc 		const io_wait_ret ret = io_wait(pair, -1, true);
611*0a6a1f1dSLionel Sambuc 		signals_block();
612*0a6a1f1dSLionel Sambuc 
613*0a6a1f1dSLionel Sambuc 		if (ret != IO_WAIT_MORE)
614*0a6a1f1dSLionel Sambuc 			goto error;
615*0a6a1f1dSLionel Sambuc 	}
616*0a6a1f1dSLionel Sambuc #endif
617*0a6a1f1dSLionel Sambuc 
618*0a6a1f1dSLionel Sambuc #ifdef HAVE_POSIX_FADVISE
619*0a6a1f1dSLionel Sambuc 	// It will fail with some special files like FIFOs but that is fine.
620*0a6a1f1dSLionel Sambuc 	(void)posix_fadvise(pair->src_fd, 0, 0, POSIX_FADV_SEQUENTIAL);
62111be35a1SLionel Sambuc #endif
6225a645f22SBen Gras 
6235a645f22SBen Gras 	return false;
6245a645f22SBen Gras 
6255a645f22SBen Gras error_msg:
6265a645f22SBen Gras 	message_error("%s: %s", pair->src_name, strerror(errno));
6275a645f22SBen Gras error:
6285a645f22SBen Gras 	(void)close(pair->src_fd);
6295a645f22SBen Gras 	return true;
6305a645f22SBen Gras }
6315a645f22SBen Gras 
6325a645f22SBen Gras 
6335a645f22SBen Gras extern file_pair *
io_open_src(const char * src_name)6345a645f22SBen Gras io_open_src(const char *src_name)
6355a645f22SBen Gras {
6365a645f22SBen Gras 	if (is_empty_filename(src_name))
6375a645f22SBen Gras 		return NULL;
6385a645f22SBen Gras 
6395a645f22SBen Gras 	// Since we have only one file open at a time, we can use
6405a645f22SBen Gras 	// a statically allocated structure.
6415a645f22SBen Gras 	static file_pair pair;
6425a645f22SBen Gras 
6435a645f22SBen Gras 	pair = (file_pair){
6445a645f22SBen Gras 		.src_name = src_name,
6455a645f22SBen Gras 		.dest_name = NULL,
6465a645f22SBen Gras 		.src_fd = -1,
6475a645f22SBen Gras 		.dest_fd = -1,
6485a645f22SBen Gras 		.src_eof = false,
6495a645f22SBen Gras 		.dest_try_sparse = false,
6505a645f22SBen Gras 		.dest_pending_sparse = 0,
6515a645f22SBen Gras 	};
6525a645f22SBen Gras 
6535a645f22SBen Gras 	// Block the signals, for which we have a custom signal handler, so
6545a645f22SBen Gras 	// that we don't need to worry about EINTR.
6555a645f22SBen Gras 	signals_block();
6565a645f22SBen Gras 	const bool error = io_open_src_real(&pair);
6575a645f22SBen Gras 	signals_unblock();
6585a645f22SBen Gras 
6595a645f22SBen Gras 	return error ? NULL : &pair;
6605a645f22SBen Gras }
6615a645f22SBen Gras 
6625a645f22SBen Gras 
6635a645f22SBen Gras /// \brief      Closes source file of the file_pair structure
6645a645f22SBen Gras ///
6655a645f22SBen Gras /// \param      pair    File whose src_fd should be closed
6665a645f22SBen Gras /// \param      success If true, the file will be removed from the disk if
6675a645f22SBen Gras ///                     closing succeeds and --keep hasn't been used.
6685a645f22SBen Gras static void
io_close_src(file_pair * pair,bool success)6695a645f22SBen Gras io_close_src(file_pair *pair, bool success)
6705a645f22SBen Gras {
671*0a6a1f1dSLionel Sambuc #ifndef TUKLIB_DOSLIKE
672*0a6a1f1dSLionel Sambuc 	if (restore_stdin_flags) {
673*0a6a1f1dSLionel Sambuc 		assert(pair->src_fd == STDIN_FILENO);
674*0a6a1f1dSLionel Sambuc 
675*0a6a1f1dSLionel Sambuc 		restore_stdin_flags = false;
676*0a6a1f1dSLionel Sambuc 
677*0a6a1f1dSLionel Sambuc 		if (fcntl(STDIN_FILENO, F_SETFL, stdin_flags) == -1)
678*0a6a1f1dSLionel Sambuc 			message_error(_("Error restoring the status flags "
679*0a6a1f1dSLionel Sambuc 					"to standard input: %s"),
680*0a6a1f1dSLionel Sambuc 					strerror(errno));
681*0a6a1f1dSLionel Sambuc 	}
682*0a6a1f1dSLionel Sambuc #endif
683*0a6a1f1dSLionel Sambuc 
6845a645f22SBen Gras 	if (pair->src_fd != STDIN_FILENO && pair->src_fd != -1) {
6855a645f22SBen Gras #ifdef TUKLIB_DOSLIKE
6865a645f22SBen Gras 		(void)close(pair->src_fd);
6875a645f22SBen Gras #endif
6885a645f22SBen Gras 
6895a645f22SBen Gras 		// If we are going to unlink(), do it before closing the file.
6905a645f22SBen Gras 		// This way there's no risk that someone replaces the file and
6915a645f22SBen Gras 		// happens to get same inode number, which would make us
6925a645f22SBen Gras 		// unlink() wrong file.
6935a645f22SBen Gras 		//
6945a645f22SBen Gras 		// NOTE: DOS-like systems are an exception to this, because
6955a645f22SBen Gras 		// they don't allow unlinking files that are open. *sigh*
6965a645f22SBen Gras 		if (success && !opt_keep_original)
6975a645f22SBen Gras 			io_unlink(pair->src_name, &pair->src_st);
6985a645f22SBen Gras 
6995a645f22SBen Gras #ifndef TUKLIB_DOSLIKE
7005a645f22SBen Gras 		(void)close(pair->src_fd);
7015a645f22SBen Gras #endif
7025a645f22SBen Gras 	}
7035a645f22SBen Gras 
7045a645f22SBen Gras 	return;
7055a645f22SBen Gras }
7065a645f22SBen Gras 
7075a645f22SBen Gras 
7085a645f22SBen Gras static bool
io_open_dest_real(file_pair * pair)7095a645f22SBen Gras io_open_dest_real(file_pair *pair)
7105a645f22SBen Gras {
7115a645f22SBen Gras 	if (opt_stdout || pair->src_fd == STDIN_FILENO) {
7125a645f22SBen Gras 		// We don't modify or free() this.
7135a645f22SBen Gras 		pair->dest_name = (char *)"(stdout)";
7145a645f22SBen Gras 		pair->dest_fd = STDOUT_FILENO;
7155a645f22SBen Gras #ifdef TUKLIB_DOSLIKE
7165a645f22SBen Gras 		setmode(STDOUT_FILENO, O_BINARY);
717*0a6a1f1dSLionel Sambuc #else
718*0a6a1f1dSLionel Sambuc 		// Try to set O_NONBLOCK if it isn't already set.
719*0a6a1f1dSLionel Sambuc 		// If it fails, we assume that stdout is non-blocking
720*0a6a1f1dSLionel Sambuc 		// in practice. See the comments in io_open_src_real()
721*0a6a1f1dSLionel Sambuc 		// for similar situation with stdin.
722*0a6a1f1dSLionel Sambuc 		//
723*0a6a1f1dSLionel Sambuc 		// NOTE: O_APPEND may be unset later in this function
724*0a6a1f1dSLionel Sambuc 		// and it relies on stdout_flags being set here.
725*0a6a1f1dSLionel Sambuc 		stdout_flags = fcntl(STDOUT_FILENO, F_GETFL);
726*0a6a1f1dSLionel Sambuc 		if (stdout_flags == -1) {
727*0a6a1f1dSLionel Sambuc 			message_error(_("Error getting the file status flags "
728*0a6a1f1dSLionel Sambuc 					"from standard output: %s"),
729*0a6a1f1dSLionel Sambuc 					strerror(errno));
730*0a6a1f1dSLionel Sambuc 			return true;
731*0a6a1f1dSLionel Sambuc 		}
732*0a6a1f1dSLionel Sambuc 
733*0a6a1f1dSLionel Sambuc 		if ((stdout_flags & O_NONBLOCK) == 0
734*0a6a1f1dSLionel Sambuc 				&& fcntl(STDOUT_FILENO, F_SETFL,
735*0a6a1f1dSLionel Sambuc 					stdout_flags | O_NONBLOCK) != -1)
736*0a6a1f1dSLionel Sambuc 				restore_stdout_flags = true;
7375a645f22SBen Gras #endif
7385a645f22SBen Gras 	} else {
7395a645f22SBen Gras 		pair->dest_name = suffix_get_dest_name(pair->src_name);
7405a645f22SBen Gras 		if (pair->dest_name == NULL)
7415a645f22SBen Gras 			return true;
7425a645f22SBen Gras 
743*0a6a1f1dSLionel Sambuc #ifdef __DJGPP__
744*0a6a1f1dSLionel Sambuc 		struct stat st;
745*0a6a1f1dSLionel Sambuc 		if (stat(pair->dest_name, &st) == 0) {
746*0a6a1f1dSLionel Sambuc 			// Check that it isn't a special file like "prn".
747*0a6a1f1dSLionel Sambuc 			if (st.st_dev == -1) {
748*0a6a1f1dSLionel Sambuc 				message_error("%s: Refusing to write to "
749*0a6a1f1dSLionel Sambuc 						"a DOS special file",
750*0a6a1f1dSLionel Sambuc 						pair->dest_name);
751*0a6a1f1dSLionel Sambuc 				free(pair->dest_name);
752*0a6a1f1dSLionel Sambuc 				return true;
753*0a6a1f1dSLionel Sambuc 			}
754*0a6a1f1dSLionel Sambuc 
755*0a6a1f1dSLionel Sambuc 			// Check that we aren't overwriting the source file.
756*0a6a1f1dSLionel Sambuc 			if (st.st_dev == pair->src_st.st_dev
757*0a6a1f1dSLionel Sambuc 					&& st.st_ino == pair->src_st.st_ino) {
758*0a6a1f1dSLionel Sambuc 				message_error("%s: Output file is the same "
759*0a6a1f1dSLionel Sambuc 						"as the input file",
760*0a6a1f1dSLionel Sambuc 						pair->dest_name);
761*0a6a1f1dSLionel Sambuc 				free(pair->dest_name);
762*0a6a1f1dSLionel Sambuc 				return true;
763*0a6a1f1dSLionel Sambuc 			}
764*0a6a1f1dSLionel Sambuc 		}
765*0a6a1f1dSLionel Sambuc #endif
766*0a6a1f1dSLionel Sambuc 
7675a645f22SBen Gras 		// If --force was used, unlink the target file first.
7685a645f22SBen Gras 		if (opt_force && unlink(pair->dest_name) && errno != ENOENT) {
7695a645f22SBen Gras 			message_error(_("%s: Cannot remove: %s"),
7705a645f22SBen Gras 					pair->dest_name, strerror(errno));
7715a645f22SBen Gras 			free(pair->dest_name);
7725a645f22SBen Gras 			return true;
7735a645f22SBen Gras 		}
7745a645f22SBen Gras 
7755a645f22SBen Gras 		// Open the file.
776*0a6a1f1dSLionel Sambuc 		int flags = O_WRONLY | O_BINARY | O_NOCTTY
7775a645f22SBen Gras 				| O_CREAT | O_EXCL;
778*0a6a1f1dSLionel Sambuc #ifndef TUKLIB_DOSLIKE
779*0a6a1f1dSLionel Sambuc 		flags |= O_NONBLOCK;
780*0a6a1f1dSLionel Sambuc #endif
7815a645f22SBen Gras 		const mode_t mode = S_IRUSR | S_IWUSR;
7825a645f22SBen Gras 		pair->dest_fd = open(pair->dest_name, flags, mode);
7835a645f22SBen Gras 
7845a645f22SBen Gras 		if (pair->dest_fd == -1) {
7855a645f22SBen Gras 			message_error("%s: %s", pair->dest_name,
7865a645f22SBen Gras 					strerror(errno));
7875a645f22SBen Gras 			free(pair->dest_name);
7885a645f22SBen Gras 			return true;
7895a645f22SBen Gras 		}
7905a645f22SBen Gras 	}
7915a645f22SBen Gras 
792*0a6a1f1dSLionel Sambuc #ifndef TUKLIB_DOSLIKE
793*0a6a1f1dSLionel Sambuc 	// dest_st isn't used on DOS-like systems except as a dummy
794*0a6a1f1dSLionel Sambuc 	// argument to io_unlink(), so don't fstat() on such systems.
7955a645f22SBen Gras 	if (fstat(pair->dest_fd, &pair->dest_st)) {
796*0a6a1f1dSLionel Sambuc 		// If fstat() really fails, we have a safe fallback here.
7975a645f22SBen Gras #	if defined(__VMS)
7985a645f22SBen Gras 		pair->dest_st.st_ino[0] = 0;
7995a645f22SBen Gras 		pair->dest_st.st_ino[1] = 0;
8005a645f22SBen Gras 		pair->dest_st.st_ino[2] = 0;
801*0a6a1f1dSLionel Sambuc #	else
8025a645f22SBen Gras 		pair->dest_st.st_dev = 0;
8035a645f22SBen Gras 		pair->dest_st.st_ino = 0;
8045a645f22SBen Gras #	endif
8055a645f22SBen Gras 	} else if (try_sparse && opt_mode == MODE_DECOMPRESS) {
8065a645f22SBen Gras 		// When writing to standard output, we need to be extra
8075a645f22SBen Gras 		// careful:
8085a645f22SBen Gras 		//  - It may be connected to something else than
8095a645f22SBen Gras 		//    a regular file.
8105a645f22SBen Gras 		//  - We aren't necessarily writing to a new empty file
8115a645f22SBen Gras 		//    or to the end of an existing file.
8125a645f22SBen Gras 		//  - O_APPEND may be active.
8135a645f22SBen Gras 		//
8145a645f22SBen Gras 		// TODO: I'm keeping this disabled for DOS-like systems
8155a645f22SBen Gras 		// for now. FAT doesn't support sparse files, but NTFS
8165a645f22SBen Gras 		// does, so maybe this should be enabled on Windows after
8175a645f22SBen Gras 		// some testing.
8185a645f22SBen Gras 		if (pair->dest_fd == STDOUT_FILENO) {
8195a645f22SBen Gras 			if (!S_ISREG(pair->dest_st.st_mode))
8205a645f22SBen Gras 				return false;
8215a645f22SBen Gras 
822*0a6a1f1dSLionel Sambuc 			if (stdout_flags & O_APPEND) {
8235a645f22SBen Gras 				// Creating a sparse file is not possible
8245a645f22SBen Gras 				// when O_APPEND is active (it's used by
8255a645f22SBen Gras 				// shell's >> redirection). As I understand
8265a645f22SBen Gras 				// it, it is safe to temporarily disable
8275a645f22SBen Gras 				// O_APPEND in xz, because if someone
8285a645f22SBen Gras 				// happened to write to the same file at the
8295a645f22SBen Gras 				// same time, results would be bad anyway
8305a645f22SBen Gras 				// (users shouldn't assume that xz uses any
8315a645f22SBen Gras 				// specific block size when writing data).
8325a645f22SBen Gras 				//
8335a645f22SBen Gras 				// The write position may be something else
8345a645f22SBen Gras 				// than the end of the file, so we must fix
8355a645f22SBen Gras 				// it to start writing at the end of the file
8365a645f22SBen Gras 				// to imitate O_APPEND.
8375a645f22SBen Gras 				if (lseek(STDOUT_FILENO, 0, SEEK_END) == -1)
8385a645f22SBen Gras 					return false;
8395a645f22SBen Gras 
840*0a6a1f1dSLionel Sambuc 				// Construct the new file status flags.
841*0a6a1f1dSLionel Sambuc 				// If O_NONBLOCK was set earlier in this
842*0a6a1f1dSLionel Sambuc 				// function, it must be kept here too.
843*0a6a1f1dSLionel Sambuc 				int flags = stdout_flags & ~O_APPEND;
844*0a6a1f1dSLionel Sambuc 				if (restore_stdout_flags)
845*0a6a1f1dSLionel Sambuc 					flags |= O_NONBLOCK;
846*0a6a1f1dSLionel Sambuc 
847*0a6a1f1dSLionel Sambuc 				// If this fcntl() fails, we continue but won't
848*0a6a1f1dSLionel Sambuc 				// try to create sparse output. The original
849*0a6a1f1dSLionel Sambuc 				// flags will still be restored if needed (to
850*0a6a1f1dSLionel Sambuc 				// unset O_NONBLOCK) when the file is finished.
851*0a6a1f1dSLionel Sambuc 				if (fcntl(STDOUT_FILENO, F_SETFL, flags) == -1)
8525a645f22SBen Gras 					return false;
8535a645f22SBen Gras 
854*0a6a1f1dSLionel Sambuc 				// Disabling O_APPEND succeeded. Mark
855*0a6a1f1dSLionel Sambuc 				// that the flags should be restored
856*0a6a1f1dSLionel Sambuc 				// in io_close_dest(). (This may have already
857*0a6a1f1dSLionel Sambuc 				// been set when enabling O_NONBLOCK.)
858*0a6a1f1dSLionel Sambuc 				restore_stdout_flags = true;
8595a645f22SBen Gras 
8605a645f22SBen Gras 			} else if (lseek(STDOUT_FILENO, 0, SEEK_CUR)
8615a645f22SBen Gras 					!= pair->dest_st.st_size) {
8625a645f22SBen Gras 				// Writing won't start exactly at the end
8635a645f22SBen Gras 				// of the file. We cannot use sparse output,
8645a645f22SBen Gras 				// because it would probably corrupt the file.
8655a645f22SBen Gras 				return false;
8665a645f22SBen Gras 			}
8675a645f22SBen Gras 		}
8685a645f22SBen Gras 
8695a645f22SBen Gras 		pair->dest_try_sparse = true;
8705a645f22SBen Gras 	}
871*0a6a1f1dSLionel Sambuc #endif
8725a645f22SBen Gras 
8735a645f22SBen Gras 	return false;
8745a645f22SBen Gras }
8755a645f22SBen Gras 
8765a645f22SBen Gras 
8775a645f22SBen Gras extern bool
io_open_dest(file_pair * pair)8785a645f22SBen Gras io_open_dest(file_pair *pair)
8795a645f22SBen Gras {
8805a645f22SBen Gras 	signals_block();
8815a645f22SBen Gras 	const bool ret = io_open_dest_real(pair);
8825a645f22SBen Gras 	signals_unblock();
8835a645f22SBen Gras 	return ret;
8845a645f22SBen Gras }
8855a645f22SBen Gras 
8865a645f22SBen Gras 
8875a645f22SBen Gras /// \brief      Closes destination file of the file_pair structure
8885a645f22SBen Gras ///
8895a645f22SBen Gras /// \param      pair    File whose dest_fd should be closed
8905a645f22SBen Gras /// \param      success If false, the file will be removed from the disk.
8915a645f22SBen Gras ///
8925a645f22SBen Gras /// \return     Zero if closing succeeds. On error, -1 is returned and
8935a645f22SBen Gras ///             error message printed.
8945a645f22SBen Gras static bool
io_close_dest(file_pair * pair,bool success)8955a645f22SBen Gras io_close_dest(file_pair *pair, bool success)
8965a645f22SBen Gras {
8975a645f22SBen Gras #ifndef TUKLIB_DOSLIKE
8985a645f22SBen Gras 	// If io_open_dest() has disabled O_APPEND, restore it here.
899*0a6a1f1dSLionel Sambuc 	if (restore_stdout_flags) {
9005a645f22SBen Gras 		assert(pair->dest_fd == STDOUT_FILENO);
9015a645f22SBen Gras 
902*0a6a1f1dSLionel Sambuc 		restore_stdout_flags = false;
9035a645f22SBen Gras 
904*0a6a1f1dSLionel Sambuc 		if (fcntl(STDOUT_FILENO, F_SETFL, stdout_flags) == -1) {
9055a645f22SBen Gras 			message_error(_("Error restoring the O_APPEND flag "
9065a645f22SBen Gras 					"to standard output: %s"),
9075a645f22SBen Gras 					strerror(errno));
9085a645f22SBen Gras 			return true;
9095a645f22SBen Gras 		}
9105a645f22SBen Gras 	}
9115a645f22SBen Gras #endif
9125a645f22SBen Gras 
9135a645f22SBen Gras 	if (pair->dest_fd == -1 || pair->dest_fd == STDOUT_FILENO)
9145a645f22SBen Gras 		return false;
9155a645f22SBen Gras 
9165a645f22SBen Gras 	if (close(pair->dest_fd)) {
9175a645f22SBen Gras 		message_error(_("%s: Closing the file failed: %s"),
9185a645f22SBen Gras 				pair->dest_name, strerror(errno));
9195a645f22SBen Gras 
9205a645f22SBen Gras 		// Closing destination file failed, so we cannot trust its
9215a645f22SBen Gras 		// contents. Get rid of junk:
9225a645f22SBen Gras 		io_unlink(pair->dest_name, &pair->dest_st);
9235a645f22SBen Gras 		free(pair->dest_name);
9245a645f22SBen Gras 		return true;
9255a645f22SBen Gras 	}
9265a645f22SBen Gras 
9275a645f22SBen Gras 	// If the operation using this file wasn't successful, we git rid
9285a645f22SBen Gras 	// of the junk file.
9295a645f22SBen Gras 	if (!success)
9305a645f22SBen Gras 		io_unlink(pair->dest_name, &pair->dest_st);
9315a645f22SBen Gras 
9325a645f22SBen Gras 	free(pair->dest_name);
9335a645f22SBen Gras 
9345a645f22SBen Gras 	return false;
9355a645f22SBen Gras }
9365a645f22SBen Gras 
9375a645f22SBen Gras 
9385a645f22SBen Gras extern void
io_close(file_pair * pair,bool success)9395a645f22SBen Gras io_close(file_pair *pair, bool success)
9405a645f22SBen Gras {
9415a645f22SBen Gras 	// Take care of sparseness at the end of the output file.
9425a645f22SBen Gras 	if (success && pair->dest_try_sparse
9435a645f22SBen Gras 			&& pair->dest_pending_sparse > 0) {
9445a645f22SBen Gras 		// Seek forward one byte less than the size of the pending
9455a645f22SBen Gras 		// hole, then write one zero-byte. This way the file grows
9465a645f22SBen Gras 		// to its correct size. An alternative would be to use
9475a645f22SBen Gras 		// ftruncate() but that isn't portable enough (e.g. it
9485a645f22SBen Gras 		// doesn't work with FAT on Linux; FAT isn't that important
9495a645f22SBen Gras 		// since it doesn't support sparse files anyway, but we don't
9505a645f22SBen Gras 		// want to create corrupt files on it).
9515a645f22SBen Gras 		if (lseek(pair->dest_fd, pair->dest_pending_sparse - 1,
9525a645f22SBen Gras 				SEEK_CUR) == -1) {
9535a645f22SBen Gras 			message_error(_("%s: Seeking failed when trying "
9545a645f22SBen Gras 					"to create a sparse file: %s"),
9555a645f22SBen Gras 					pair->dest_name, strerror(errno));
9565a645f22SBen Gras 			success = false;
9575a645f22SBen Gras 		} else {
9585a645f22SBen Gras 			const uint8_t zero[1] = { '\0' };
9595a645f22SBen Gras 			if (io_write_buf(pair, zero, 1))
9605a645f22SBen Gras 				success = false;
9615a645f22SBen Gras 		}
9625a645f22SBen Gras 	}
9635a645f22SBen Gras 
9645a645f22SBen Gras 	signals_block();
9655a645f22SBen Gras 
9665a645f22SBen Gras 	// Copy the file attributes. We need to skip this if destination
9675a645f22SBen Gras 	// file isn't open or it is standard output.
9685a645f22SBen Gras 	if (success && pair->dest_fd != -1 && pair->dest_fd != STDOUT_FILENO)
9695a645f22SBen Gras 		io_copy_attrs(pair);
9705a645f22SBen Gras 
9715a645f22SBen Gras 	// Close the destination first. If it fails, we must not remove
9725a645f22SBen Gras 	// the source file!
9735a645f22SBen Gras 	if (io_close_dest(pair, success))
9745a645f22SBen Gras 		success = false;
9755a645f22SBen Gras 
9765a645f22SBen Gras 	// Close the source file, and unlink it if the operation using this
9775a645f22SBen Gras 	// file pair was successful and we haven't requested to keep the
9785a645f22SBen Gras 	// source file.
9795a645f22SBen Gras 	io_close_src(pair, success);
9805a645f22SBen Gras 
9815a645f22SBen Gras 	signals_unblock();
9825a645f22SBen Gras 
9835a645f22SBen Gras 	return;
9845a645f22SBen Gras }
9855a645f22SBen Gras 
9865a645f22SBen Gras 
987*0a6a1f1dSLionel Sambuc extern void
io_fix_src_pos(file_pair * pair,size_t rewind_size)988*0a6a1f1dSLionel Sambuc io_fix_src_pos(file_pair *pair, size_t rewind_size)
989*0a6a1f1dSLionel Sambuc {
990*0a6a1f1dSLionel Sambuc 	assert(rewind_size <= IO_BUFFER_SIZE);
991*0a6a1f1dSLionel Sambuc 
992*0a6a1f1dSLionel Sambuc 	if (rewind_size > 0) {
993*0a6a1f1dSLionel Sambuc 		// This doesn't need to work on unseekable file descriptors,
994*0a6a1f1dSLionel Sambuc 		// so just ignore possible errors.
995*0a6a1f1dSLionel Sambuc 		(void)lseek(pair->src_fd, -(off_t)(rewind_size), SEEK_CUR);
996*0a6a1f1dSLionel Sambuc 	}
997*0a6a1f1dSLionel Sambuc 
998*0a6a1f1dSLionel Sambuc 	return;
999*0a6a1f1dSLionel Sambuc }
1000*0a6a1f1dSLionel Sambuc 
1001*0a6a1f1dSLionel Sambuc 
10025a645f22SBen Gras extern size_t
io_read(file_pair * pair,io_buf * buf_union,size_t size)10035a645f22SBen Gras io_read(file_pair *pair, io_buf *buf_union, size_t size)
10045a645f22SBen Gras {
10055a645f22SBen Gras 	// We use small buffers here.
10065a645f22SBen Gras 	assert(size < SSIZE_MAX);
10075a645f22SBen Gras 
10085a645f22SBen Gras 	uint8_t *buf = buf_union->u8;
10095a645f22SBen Gras 	size_t left = size;
10105a645f22SBen Gras 
10115a645f22SBen Gras 	while (left > 0) {
10125a645f22SBen Gras 		const ssize_t amount = read(pair->src_fd, buf, left);
10135a645f22SBen Gras 
10145a645f22SBen Gras 		if (amount == 0) {
10155a645f22SBen Gras 			pair->src_eof = true;
10165a645f22SBen Gras 			break;
10175a645f22SBen Gras 		}
10185a645f22SBen Gras 
10195a645f22SBen Gras 		if (amount == -1) {
10205a645f22SBen Gras 			if (errno == EINTR) {
10215a645f22SBen Gras 				if (user_abort)
10225a645f22SBen Gras 					return SIZE_MAX;
10235a645f22SBen Gras 
10245a645f22SBen Gras 				continue;
10255a645f22SBen Gras 			}
10265a645f22SBen Gras 
1027*0a6a1f1dSLionel Sambuc #ifndef TUKLIB_DOSLIKE
1028*0a6a1f1dSLionel Sambuc 			if (errno == EAGAIN || errno == EWOULDBLOCK) {
1029*0a6a1f1dSLionel Sambuc 				const io_wait_ret ret = io_wait(pair,
1030*0a6a1f1dSLionel Sambuc 						mytime_get_flush_timeout(),
1031*0a6a1f1dSLionel Sambuc 						true);
1032*0a6a1f1dSLionel Sambuc 				switch (ret) {
1033*0a6a1f1dSLionel Sambuc 				case IO_WAIT_MORE:
1034*0a6a1f1dSLionel Sambuc 					continue;
1035*0a6a1f1dSLionel Sambuc 
1036*0a6a1f1dSLionel Sambuc 				case IO_WAIT_ERROR:
1037*0a6a1f1dSLionel Sambuc 					return SIZE_MAX;
1038*0a6a1f1dSLionel Sambuc 
1039*0a6a1f1dSLionel Sambuc 				case IO_WAIT_TIMEOUT:
1040*0a6a1f1dSLionel Sambuc 					return size - left;
1041*0a6a1f1dSLionel Sambuc 
1042*0a6a1f1dSLionel Sambuc 				default:
1043*0a6a1f1dSLionel Sambuc 					message_bug();
1044*0a6a1f1dSLionel Sambuc 				}
1045*0a6a1f1dSLionel Sambuc 			}
1046*0a6a1f1dSLionel Sambuc #endif
1047*0a6a1f1dSLionel Sambuc 
10485a645f22SBen Gras 			message_error(_("%s: Read error: %s"),
10495a645f22SBen Gras 					pair->src_name, strerror(errno));
10505a645f22SBen Gras 
10515a645f22SBen Gras 			return SIZE_MAX;
10525a645f22SBen Gras 		}
10535a645f22SBen Gras 
10545a645f22SBen Gras 		buf += (size_t)(amount);
10555a645f22SBen Gras 		left -= (size_t)(amount);
10565a645f22SBen Gras 	}
10575a645f22SBen Gras 
10585a645f22SBen Gras 	return size - left;
10595a645f22SBen Gras }
10605a645f22SBen Gras 
10615a645f22SBen Gras 
10625a645f22SBen Gras extern bool
io_pread(file_pair * pair,io_buf * buf,size_t size,off_t pos)10635a645f22SBen Gras io_pread(file_pair *pair, io_buf *buf, size_t size, off_t pos)
10645a645f22SBen Gras {
10655a645f22SBen Gras 	// Using lseek() and read() is more portable than pread() and
10665a645f22SBen Gras 	// for us it is as good as real pread().
10675a645f22SBen Gras 	if (lseek(pair->src_fd, pos, SEEK_SET) != pos) {
10685a645f22SBen Gras 		message_error(_("%s: Error seeking the file: %s"),
10695a645f22SBen Gras 				pair->src_name, strerror(errno));
10705a645f22SBen Gras 		return true;
10715a645f22SBen Gras 	}
10725a645f22SBen Gras 
10735a645f22SBen Gras 	const size_t amount = io_read(pair, buf, size);
10745a645f22SBen Gras 	if (amount == SIZE_MAX)
10755a645f22SBen Gras 		return true;
10765a645f22SBen Gras 
10775a645f22SBen Gras 	if (amount != size) {
10785a645f22SBen Gras 		message_error(_("%s: Unexpected end of file"),
10795a645f22SBen Gras 				pair->src_name);
10805a645f22SBen Gras 		return true;
10815a645f22SBen Gras 	}
10825a645f22SBen Gras 
10835a645f22SBen Gras 	return false;
10845a645f22SBen Gras }
10855a645f22SBen Gras 
10865a645f22SBen Gras 
10875a645f22SBen Gras static bool
is_sparse(const io_buf * buf)10885a645f22SBen Gras is_sparse(const io_buf *buf)
10895a645f22SBen Gras {
10905a645f22SBen Gras 	assert(IO_BUFFER_SIZE % sizeof(uint64_t) == 0);
10915a645f22SBen Gras 
10925a645f22SBen Gras 	for (size_t i = 0; i < ARRAY_SIZE(buf->u64); ++i)
10935a645f22SBen Gras 		if (buf->u64[i] != 0)
10945a645f22SBen Gras 			return false;
10955a645f22SBen Gras 
10965a645f22SBen Gras 	return true;
10975a645f22SBen Gras }
10985a645f22SBen Gras 
10995a645f22SBen Gras 
11005a645f22SBen Gras static bool
io_write_buf(file_pair * pair,const uint8_t * buf,size_t size)11015a645f22SBen Gras io_write_buf(file_pair *pair, const uint8_t *buf, size_t size)
11025a645f22SBen Gras {
11035a645f22SBen Gras 	assert(size < SSIZE_MAX);
11045a645f22SBen Gras 
11055a645f22SBen Gras 	while (size > 0) {
11065a645f22SBen Gras 		const ssize_t amount = write(pair->dest_fd, buf, size);
11075a645f22SBen Gras 		if (amount == -1) {
11085a645f22SBen Gras 			if (errno == EINTR) {
11095a645f22SBen Gras 				if (user_abort)
1110*0a6a1f1dSLionel Sambuc 					return true;
11115a645f22SBen Gras 
11125a645f22SBen Gras 				continue;
11135a645f22SBen Gras 			}
11145a645f22SBen Gras 
1115*0a6a1f1dSLionel Sambuc #ifndef TUKLIB_DOSLIKE
1116*0a6a1f1dSLionel Sambuc 			if (errno == EAGAIN || errno == EWOULDBLOCK) {
1117*0a6a1f1dSLionel Sambuc 				if (io_wait(pair, -1, false) == IO_WAIT_MORE)
1118*0a6a1f1dSLionel Sambuc 					continue;
1119*0a6a1f1dSLionel Sambuc 
1120*0a6a1f1dSLionel Sambuc 				return true;
1121*0a6a1f1dSLionel Sambuc 			}
1122*0a6a1f1dSLionel Sambuc #endif
1123*0a6a1f1dSLionel Sambuc 
11245a645f22SBen Gras 			// Handle broken pipe specially. gzip and bzip2
11255a645f22SBen Gras 			// don't print anything on SIGPIPE. In addition,
11265a645f22SBen Gras 			// gzip --quiet uses exit status 2 (warning) on
11275a645f22SBen Gras 			// broken pipe instead of whatever raise(SIGPIPE)
11285a645f22SBen Gras 			// would make it return. It is there to hide "Broken
11295a645f22SBen Gras 			// pipe" message on some old shells (probably old
11305a645f22SBen Gras 			// GNU bash).
11315a645f22SBen Gras 			//
11325a645f22SBen Gras 			// We don't do anything special with --quiet, which
11335a645f22SBen Gras 			// is what bzip2 does too. If we get SIGPIPE, we
11345a645f22SBen Gras 			// will handle it like other signals by setting
11355a645f22SBen Gras 			// user_abort, and get EPIPE here.
11365a645f22SBen Gras 			if (errno != EPIPE)
11375a645f22SBen Gras 				message_error(_("%s: Write error: %s"),
11385a645f22SBen Gras 					pair->dest_name, strerror(errno));
11395a645f22SBen Gras 
11405a645f22SBen Gras 			return true;
11415a645f22SBen Gras 		}
11425a645f22SBen Gras 
11435a645f22SBen Gras 		buf += (size_t)(amount);
11445a645f22SBen Gras 		size -= (size_t)(amount);
11455a645f22SBen Gras 	}
11465a645f22SBen Gras 
11475a645f22SBen Gras 	return false;
11485a645f22SBen Gras }
11495a645f22SBen Gras 
11505a645f22SBen Gras 
11515a645f22SBen Gras extern bool
io_write(file_pair * pair,const io_buf * buf,size_t size)11525a645f22SBen Gras io_write(file_pair *pair, const io_buf *buf, size_t size)
11535a645f22SBen Gras {
11545a645f22SBen Gras 	assert(size <= IO_BUFFER_SIZE);
11555a645f22SBen Gras 
11565a645f22SBen Gras 	if (pair->dest_try_sparse) {
11575a645f22SBen Gras 		// Check if the block is sparse (contains only zeros). If it
11585a645f22SBen Gras 		// sparse, we just store the amount and return. We will take
11595a645f22SBen Gras 		// care of actually skipping over the hole when we hit the
11605a645f22SBen Gras 		// next data block or close the file.
11615a645f22SBen Gras 		//
11625a645f22SBen Gras 		// Since io_close() requires that dest_pending_sparse > 0
11635a645f22SBen Gras 		// if the file ends with sparse block, we must also return
11645a645f22SBen Gras 		// if size == 0 to avoid doing the lseek().
11655a645f22SBen Gras 		if (size == IO_BUFFER_SIZE) {
11665a645f22SBen Gras 			if (is_sparse(buf)) {
11675a645f22SBen Gras 				pair->dest_pending_sparse += size;
11685a645f22SBen Gras 				return false;
11695a645f22SBen Gras 			}
11705a645f22SBen Gras 		} else if (size == 0) {
11715a645f22SBen Gras 			return false;
11725a645f22SBen Gras 		}
11735a645f22SBen Gras 
11745a645f22SBen Gras 		// This is not a sparse block. If we have a pending hole,
11755a645f22SBen Gras 		// skip it now.
11765a645f22SBen Gras 		if (pair->dest_pending_sparse > 0) {
11775a645f22SBen Gras 			if (lseek(pair->dest_fd, pair->dest_pending_sparse,
11785a645f22SBen Gras 					SEEK_CUR) == -1) {
11795a645f22SBen Gras 				message_error(_("%s: Seeking failed when "
11805a645f22SBen Gras 						"trying to create a sparse "
11815a645f22SBen Gras 						"file: %s"), pair->dest_name,
11825a645f22SBen Gras 						strerror(errno));
11835a645f22SBen Gras 				return true;
11845a645f22SBen Gras 			}
11855a645f22SBen Gras 
11865a645f22SBen Gras 			pair->dest_pending_sparse = 0;
11875a645f22SBen Gras 		}
11885a645f22SBen Gras 	}
11895a645f22SBen Gras 
11905a645f22SBen Gras 	return io_write_buf(pair, buf->u8, size);
11915a645f22SBen Gras }
1192