+ write_directory_file ();
+}
+
+
+/* Calculate the hash of a link. */
+static size_t
+hash_link (void const *entry, size_t n_buckets)
+{
+ struct link const *l = entry;
+ uintmax_t num = l->dev ^ l->ino;
+ return num % n_buckets;
+}
+
+/* Compare two links for equality. */
+static bool
+compare_links (void const *entry1, void const *entry2)
+{
+ struct link const *link1 = entry1;
+ struct link const *link2 = entry2;
+ return ((link1->dev ^ link2->dev) | (link1->ino ^ link2->ino)) == 0;
+}
+
+static void
+unknown_file_error (char *p)
+{
+ WARN ((0, 0, _("%s: Unknown file type; file ignored"),
+ quotearg_colon (p)));
+ if (!ignore_failed_read_option)
+ exit_status = TAREXIT_FAILURE;
+}
+
+\f
+/* Handling of hard links */
+
+/* Table of all non-directories that we've written so far. Any time
+ we see another, we check the table and avoid dumping the data
+ again if we've done it once already. */
+static Hash_table *link_table;
+
+/* Try to dump stat as a hard link to another file in the archive. If
+ succeeded returns true */
+static bool
+dump_hard_link (struct tar_stat_info *st)
+{
+ if (link_table && st->stat.st_nlink > 1)
+ {
+ struct link lp;
+ struct link *duplicate;
+ off_t block_ordinal;
+ union block *blk;
+
+ lp.ino = st->stat.st_ino;
+ lp.dev = st->stat.st_dev;
+
+ if ((duplicate = hash_lookup (link_table, &lp)))
+ {
+ /* We found a link. */
+ char const *link_name = safer_name_suffix (duplicate->name, true,
+ absolute_names_option);
+
+ duplicate->nlink--;
+
+ block_ordinal = current_block_ordinal ();
+ assign_string (&st->link_name, link_name);
+ if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT)
+ < strlen (link_name))
+ write_long_link (st);
+
+ st->stat.st_size = 0;
+ blk = start_header (st);
+ if (!blk)
+ return true;
+ tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE);
+
+ blk->header.typeflag = LNKTYPE;
+ finish_header (st, blk, block_ordinal);
+
+ if (remove_files_option && unlink (st->orig_file_name) != 0)
+ unlink_error (st->orig_file_name);
+
+ return true;
+ }
+ }
+ return false;