+ if (this_is_the_archive
+ && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
+ return true;
+
+ after_backup_name = find_backup_file_name (file_name, backup_type);
+ if (! after_backup_name)
+ xalloc_die ();
+
+ if (renameat (chdir_fd, before_backup_name, chdir_fd, after_backup_name)
+ == 0)
+ {
+ if (verbose_option)
+ fprintf (stdlis, _("Renaming %s to %s\n"),
+ quote_n (0, before_backup_name),
+ quote_n (1, after_backup_name));
+ return true;
+ }
+ else
+ {
+ /* The backup operation failed. */
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot rename to %s"),
+ quotearg_colon (before_backup_name),
+ quote_n (1, after_backup_name)));
+ assign_string (&after_backup_name, 0);
+ return false;
+ }
+}
+
+/* Try to restore the recently backed up file to its original name.
+ This is usually only needed after a failed extraction. */
+void
+undo_last_backup (void)
+{
+ if (after_backup_name)
+ {
+ if (renameat (chdir_fd, after_backup_name, chdir_fd, before_backup_name)
+ != 0)
+ {
+ int e = errno;
+ ERROR ((0, e, _("%s: Cannot rename to %s"),
+ quotearg_colon (after_backup_name),
+ quote_n (1, before_backup_name)));
+ }
+ if (verbose_option)
+ fprintf (stdlis, _("Renaming %s back to %s\n"),
+ quote_n (0, after_backup_name),
+ quote_n (1, before_backup_name));
+ assign_string (&after_backup_name, 0);
+ }
+}
+
+/* Apply either stat or lstat to (NAME, BUF), depending on the
+ presence of the --dereference option. NAME is relative to the
+ most-recent argument to chdir_do. */
+int
+deref_stat (char const *name, struct stat *buf)
+{
+ return fstatat (chdir_fd, name, buf, fstatat_flags);
+}
+
+/* Read from FD into the buffer BUF with COUNT bytes. Attempt to fill
+ BUF. Wait until input is available; this matters because files are
+ opened O_NONBLOCK for security reasons, and on some file systems
+ this can cause read to fail with errno == EAGAIN. Return the
+ actual number of bytes read, zero for EOF, or
+ SAFE_READ_ERROR upon error. */
+size_t
+blocking_read (int fd, void *buf, size_t count)
+{
+ size_t bytes = safe_read (fd, buf, count);
+
+#if defined F_SETFL && O_NONBLOCK
+ if (bytes == SAFE_READ_ERROR && errno == EAGAIN)
+ {
+ int flags = fcntl (fd, F_GETFL);
+ if (0 <= flags && flags & O_NONBLOCK
+ && fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
+ bytes = safe_read (fd, buf, count);
+ }