+
+ if (unlink_first_option)
+ remove_any_file (CURRENT_FILE_NAME, recursive_unlink_option);
+
+#if O_CTG
+ /* Contiguous files (on the Masscomp) have to specify the size in
+ the open call that creates them. */
+
+ if (typeflag == CONTTYPE)
+ fd = open (CURRENT_FILE_NAME, openflag | O_CTG,
+ current_stat.st_mode, current_stat.st_size);
+ else
+ fd = open (CURRENT_FILE_NAME, openflag, current_stat.st_mode);
+
+#else /* not O_CTG */
+ if (typeflag == CONTTYPE)
+ {
+ static int conttype_diagnosed = 0;
+
+ if (!conttype_diagnosed)
+ {
+ conttype_diagnosed = 1;
+ WARN ((0, 0, _("Extracting contiguous files as regular files")));
+ }
+ }
+ fd = open (CURRENT_FILE_NAME, openflag, current_stat.st_mode);
+
+#endif /* not O_CTG */
+
+ if (fd < 0)
+ {
+ if (maybe_recoverable (CURRENT_FILE_NAME))
+ goto again_file;
+
+ ERROR ((0, errno, _("%s: Could not create file"),
+ CURRENT_FILE_NAME));
+ if (current_header->oldgnu_header.isextended)
+ skip_extended_headers ();
+ skip_file (current_stat.st_size);
+ if (backup_option)
+ undo_last_backup ();
+ break;
+ }
+
+ extract_file:
+ if (typeflag == GNUTYPE_SPARSE)
+ {
+ char *name;
+ size_t name_length_bis;
+
+ /* Kludge alert. NAME is assigned to header.name because
+ during the extraction, the space that contains the header
+ will get scribbled on, and the name will get munged, so any
+ error messages that happen to contain the filename will look
+ REAL interesting unless we do this. */
+
+ name_length_bis = strlen (CURRENT_FILE_NAME) + 1;
+ name = (char *) xmalloc (name_length_bis);
+ memcpy (name, CURRENT_FILE_NAME, name_length_bis);
+ size = current_stat.st_size;
+ extract_sparse_file (fd, &size, current_stat.st_size, name);
+ }
+ else
+ for (size = current_stat.st_size;
+ size > 0;
+ size -= written)
+ {
+ if (multi_volume_option)
+ {
+ assign_string (&save_name, current_file_name);
+ save_totsize = current_stat.st_size;
+ save_sizeleft = 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 == NULL)
+ {
+ ERROR ((0, 0, _("Unexpected EOF on archive file")));
+ break; /* FIXME: What happens, then? */
+ }
+
+ written = available_space_after (data_block);
+
+ if (written > size)
+ written = size;
+ errno = 0; /* FIXME: errno should be read-only */
+ sstatus = full_write (fd, data_block->buffer, written);
+
+ set_next_block_after ((union block *)
+ (data_block->buffer + written - 1));
+ if (sstatus == written)
+ continue;
+
+ /* Error in writing to file. Print it, skip to next file in
+ archive. */
+
+ if (sstatus < 0)
+ ERROR ((0, errno, _("%s: Could not write to file"),
+ CURRENT_FILE_NAME));
+ else
+ ERROR ((0, 0, _("%s: Could only write %lu of %lu bytes"),
+ CURRENT_FILE_NAME,
+ (unsigned long) sstatus,
+ (unsigned long) written));
+ skip_file (size - written);
+ break; /* still do the close, mod time, chmod, etc */
+ }
+
+ if (multi_volume_option)
+ assign_string (&save_name, NULL);
+
+ /* 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)
+ break;
+
+ status = close (fd);
+ if (status < 0)
+ {
+ ERROR ((0, errno, _("%s: Error while closing"), CURRENT_FILE_NAME));
+ if (backup_option)
+ undo_last_backup ();
+ }
+
+ set_stat (CURRENT_FILE_NAME, ¤t_stat, 0);
+ break;
+
+ case SYMTYPE:
+ if (to_stdout_option)
+ break;