- extract_file:
- if (current_header->header.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? */
- }
-
- /* If the file is sparse, use the sparsearray that we created
- before to lseek into the new file the proper amount, and to
- see how many bytes we want to write at that position. */
-
-#if 0
- if (current_header->header.typeflag == GNUTYPE_SPARSE)
- {
- lseek (fd, sparsearray[sparse_ind].offset, 0);
- written = sparsearray[sparse_ind++].numbytes;
- }
- else
-#endif
- written = available_space_after (data_block);
-
- if (written > size)
- written = size;
- errno = 0; /* FIXME: errno should be read-only */
- sstatus = 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 */
+ return fd;
+}
+
+static int
+extract_file (char *file_name, int typeflag)
+{
+ int fd;
+ off_t size;
+ union block *data_block;
+ int status;
+ size_t count;
+ size_t written;
+ bool interdir_made = false;
+ mode_t mode = (current_stat_info.stat.st_mode & MODE_RWX
+ & ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0));
+ mode_t current_mode = 0;
+ mode_t current_mode_mask = 0;
+
+ if (to_stdout_option)
+ fd = STDOUT_FILENO;
+ else if (to_command_option)
+ {
+ fd = sys_exec_command (file_name, 'f', ¤t_stat_info);
+ if (fd < 0)
+ {
+ skip_member ();
+ return 0;
+ }
+ }
+ else
+ {
+ while ((fd = open_output_file (file_name, typeflag, mode,
+ ¤t_mode, ¤t_mode_mask))
+ < 0)
+ {
+ int recover = maybe_recoverable (file_name, true, &interdir_made);
+ if (recover != RECOVER_OK)
+ {
+ skip_member ();
+ if (recover == RECOVER_SKIP)
+ return 0;
+ open_error (file_name);
+ return 1;
+ }
+ }
+ }
+
+ mv_begin_read (¤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? */