+ mv_begin (¤t_stat_info);
+ if (current_stat_info.is_sparse)
+ sparse_extract_file (fd, ¤t_stat_info, &size);
+ else
+ for (size = current_stat_info.stat.st_size; size > 0; )
+ {
+ mv_size_left (size);
+
+ /* Locate data, determine max length writeable, write it,
+ block that we have used the data, then check if the write
+ worked. */
+
+ data_block = find_next_block ();
+ if (! data_block)
+ {
+ ERROR ((0, 0, _("Unexpected EOF in archive")));
+ break; /* FIXME: What happens, then? */
+ }
+
+ written = available_space_after (data_block);
+
+ if (written > size)
+ written = size;
+ errno = 0;
+ count = full_write (fd, data_block->buffer, written);
+ size -= written;
+
+ set_next_block_after ((union block *)
+ (data_block->buffer + written - 1));
+ if (count != written)
+ {
+ if (!to_command_option)
+ write_error_details (file_name, count, written);
+ /* FIXME: shouldn't we restore from backup? */
+ break;
+ }
+ }
+
+ skip_file (size);
+
+ mv_end ();
+
+ /* If writing to stdout, don't try to do anything to the filename;
+ it doesn't exist, or we don't want to touch it anyway. */
+
+ if (to_stdout_option)
+ return 0;
+
+ status = close (fd);
+ if (status < 0)
+ close_error (file_name);
+
+ if (to_command_option)
+ sys_wait_command ();
+ else
+ set_stat (file_name, ¤t_stat_info, NULL, 0,
+ (old_files_option == OVERWRITE_OLD_FILES ?
+ UNKNOWN_PERMSTATUS : ARCHIVED_PERMSTATUS),
+ typeflag);
+
+ return status;
+}
+
+/* Create a placeholder file with name FILE_NAME, which will be
+ replaced after other extraction is done by a symbolic link if
+ IS_SYMLINK is true, and by a hard link otherwise. Set
+ *INTERDIR_MADE if an intermediate directory is made in the
+ process. */
+
+static int
+create_placeholder_file (char *file_name, bool is_symlink, int *interdir_made)
+{
+ int fd;
+ struct stat st;
+
+ while ((fd = open (file_name, O_WRONLY | O_CREAT | O_EXCL, 0)) < 0)
+ if (! maybe_recoverable (file_name, interdir_made))
+ break;
+
+ if (fd < 0)
+ open_error (file_name);
+ else if (fstat (fd, &st) != 0)
+ {
+ stat_error (file_name);
+ close (fd);
+ }
+ else if (close (fd) != 0)
+ close_error (file_name);
+ else
+ {
+ struct delayed_set_stat *h;
+ struct delayed_link *p =
+ xmalloc (offsetof (struct delayed_link, target)
+ + strlen (current_stat_info.link_name)
+ + 1);
+ p->next = delayed_link_head;
+ delayed_link_head = p;
+ p->dev = st.st_dev;
+ p->ino = st.st_ino;
+ p->mtime = get_stat_mtime (&st);
+ p->is_symlink = is_symlink;
+ if (is_symlink)