+ if (status == 0)
+ set_stat (file_name, ¤t_stat_info, NULL, 0, 0, SYMTYPE);
+ else
+ symlink_error (current_stat_info.link_name, file_name);
+ return status;
+
+#else
+ static int warned_once;
+
+ if (!warned_once)
+ {
+ warned_once = 1;
+ WARN ((0, 0, _("Attempting extraction of symbolic links as hard links")));
+ }
+ return extract_link (file_name, typeflag);
+#endif
+}
+
+#if S_IFCHR || S_IFBLK
+static int
+extract_node (char *file_name, int typeflag)
+{
+ int status;
+ int interdir_made = 0;
+ mode_t mode = current_stat_info.stat.st_mode & ~ current_umask;
+ mode_t invert_permissions =
+ 0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
+
+ do
+ status = mknod (file_name, mode ^ invert_permissions,
+ current_stat_info.stat.st_rdev);
+ while (status && maybe_recoverable (file_name, &interdir_made));
+
+ if (status != 0)
+ mknod_error (file_name);
+ else
+ set_stat (file_name, ¤t_stat_info, NULL, invert_permissions,
+ ARCHIVED_PERMSTATUS, typeflag);
+ return status;
+}
+#endif
+
+#if HAVE_MKFIFO || defined mkfifo
+static int
+extract_fifo (char *file_name, int typeflag)
+{
+ int status;
+ int interdir_made = 0;
+ mode_t mode = current_stat_info.stat.st_mode & ~ current_umask;
+ mode_t invert_permissions =
+ 0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
+
+ while ((status = mkfifo (file_name, mode)) != 0)
+ if (!maybe_recoverable (file_name, &interdir_made))
+ break;
+
+ if (status == 0)
+ set_stat (file_name, ¤t_stat_info, NULL, invert_permissions,
+ ARCHIVED_PERMSTATUS, typeflag);
+ else
+ mkfifo_error (file_name);
+ return status;
+}
+#endif
+
+static int
+extract_volhdr (char *file_name, int typeflag)
+{
+ if (verbose_option)
+ fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name));
+ skip_member ();
+ return 0;
+}
+
+static int
+extract_failure (char *file_name, int typeflag)
+{
+ return 1;
+}
+
+typedef int (*tar_extractor_t) (char *file_name, int typeflag);
+
+\f
+
+/* Prepare to extract a file. Find extractor function.
+ Return zero if extraction should not proceed. */
+
+static int
+prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
+{
+ int rc = 1;
+
+ if (EXTRACT_OVER_PIPE)
+ rc = 0;
+
+ /* Select the extractor */
+ switch (typeflag)
+ {
+ case GNUTYPE_SPARSE:
+ *fun = extract_file;
+ rc = 1;
+ break;
+
+ case AREGTYPE:
+ case REGTYPE:
+ case CONTTYPE:
+ /* Appears to be a file. But BSD tar uses the convention that a slash
+ suffix means a directory. */
+ if (current_stat_info.had_trailing_slash)
+ *fun = extract_dir;
+ else