uintmax_t max_n_read, off_t *total_n_read,
bool *last_write_made_hole)
{
- typedef uintptr_t word;
*last_write_made_hole = false;
*total_n_read = 0;
while (max_n_read)
{
- word *wp = NULL;
+ bool make_hole = false;
ssize_t n_read = read (src_fd, buf, MIN (max_n_read, buf_size));
if (n_read < 0)
if (make_holes)
{
- char *cp;
-
- /* Sentinel to stop loop. */
+ /* Sentinel required by is_nul(). */
buf[n_read] = '\1';
#ifdef lint
+ typedef uintptr_t word;
/* Usually, buf[n_read] is not the byte just before a "word"
(aka uintptr_t) boundary. In that case, the word-oriented
test below (*wp++ == 0) would read some uninitialized bytes
memset (buf + n_read + 1, 0, sizeof (word) - 1);
#endif
- /* Find first nonzero *word*, or the word with the sentinel. */
-
- wp = (word *) buf;
- while (*wp++ == 0)
- continue;
-
- /* Find the first nonzero *byte*, or the sentinel. */
-
- cp = (char *) (wp - 1);
- while (*cp++ == 0)
- continue;
-
- if (cp <= buf + n_read)
- /* Clear to indicate that a normal write is needed. */
- wp = NULL;
- else
+ if ((make_hole = is_nul (buf, n_read)))
{
- /* We found the sentinel, so the whole input block was zero.
- Make a hole. */
if (lseek (dest_fd, n_read, SEEK_CUR) < 0)
{
error (0, errno, _("cannot lseek %s"), quote (dst_name));
return false;
}
- *last_write_made_hole = true;
}
}
- if (!wp)
+ if (!make_hole)
{
size_t n = n_read;
if (full_write (dest_fd, buf, n) != n)
error (0, errno, _("writing %s"), quote (dst_name));
return false;
}
- *last_write_made_hole = false;
/* It is tempting to return early here upon a short read from a
regular file. That would save the final read syscall for each
file. Unfortunately that doesn't work for certain files in
/proc with linux kernels from at least 2.6.9 .. 2.6.29. */
}
+
+ *last_write_made_hole = make_hole;
}
return true;
return nread;
}
-/* Return whether the buffer consists entirely of NULs.
- Note the word after the buffer must be non NUL. */
-
-static bool _GL_ATTRIBUTE_PURE
-is_nul (const char *buf, size_t bufsize)
-{
- typedef uintptr_t word;
-
- /* Find first nonzero *word*, or the word with the sentinel. */
- word *wp = (word *) buf;
- while (*wp++ == 0)
- continue;
-
- /* Find the first nonzero *byte*, or the sentinel. */
- char *cp = (char *) (wp - 1);
- while (*cp++ == 0)
- continue;
-
- return cp > buf + bufsize;
-}
-
/* Write to FD the buffer BUF of size SIZE, processing any signals
that arrive. Return the number of bytes written, setting errno if
this is less than SIZE. Keep trying if there are partial
return (void *) (p1 - (size_t) p1 % alignment);
}
+/* Return whether the buffer consists entirely of NULs.
+ Note the word after the buffer must be non NUL. */
+
+static inline bool _GL_ATTRIBUTE_PURE
+is_nul (const char *buf, size_t bufsize)
+{
+ typedef uintptr_t word;
+
+ /* Find first nonzero *word*, or the word with the sentinel. */
+ word *wp = (word *) buf;
+ while (*wp++ == 0)
+ continue;
+
+ /* Find the first nonzero *byte*, or the sentinel. */
+ char *cp = (char *) (wp - 1);
+ while (*cp++ == 0)
+ continue;
+
+ return cp > buf + bufsize;
+}
+
/* If 10*Accum + Digit_val is larger than the maximum value for Type,
then don't update Accum and return false to indicate it would
overflow. Otherwise, set Accum to that new value and return true.