+#ifdef S_ISHIDDEN
+ if (S_ISHIDDEN (stat->stat.st_mode))
+ {
+ char *new = (char *) alloca (strlen (p) + 2);
+ if (new)
+ {
+ strcpy (new, p);
+ strcat (new, "@");
+ p = new;
+ }
+ }
+#endif
+
+ /* See if we want only new files, and check if this one is too old to
+ put in the archive. */
+
+ if ((0 < top_level || !incremental_option)
+ && !S_ISDIR (stat->stat.st_mode)
+ && stat->stat.st_mtime < newer_mtime_option
+ && (!after_date_option || stat->stat.st_ctime < newer_ctime_option))
+ {
+ if (0 < top_level)
+ WARN ((0, 0, _("%s: file is unchanged; not dumped"),
+ quotearg_colon (p)));
+ /* FIXME: recheck this return. */
+ return;
+ }
+
+ /* See if we are trying to dump the archive. */
+ if (sys_file_is_archive (stat))
+ {
+ WARN ((0, 0, _("%s: file is the archive; not dumped"),
+ quotearg_colon (p)));
+ return;
+ }
+
+ if (S_ISDIR (stat->stat.st_mode))
+ {
+ dump_dir (stat, top_level, parent_device);
+ if (atime_preserve_option)
+ utime (p, &restore_times);
+ return;
+ }
+ else if (is_avoided_name (p))
+ return;
+ else
+ {
+ /* Check for multiple links. */
+ if (dump_hard_link (stat))
+ return;
+
+ /* This is not a link to a previously dumped file, so dump it. */
+
+ if (S_ISREG (stat->stat.st_mode)
+ || S_ISCTG (stat->stat.st_mode))
+ {
+ int fd;
+ enum dump_status status;
+
+ if (file_dumpable_p (stat))
+ {
+ fd = open (stat->orig_file_name,
+ O_RDONLY | O_BINARY);
+ if (fd < 0)
+ {
+ if (!top_level && errno == ENOENT)
+ WARN ((0, 0, _("%s: File removed before we read it"),
+ quotearg_colon (stat->orig_file_name)));
+ else
+ open_diag (stat->orig_file_name);
+ return;
+ }
+ }
+ else
+ fd = -1;
+
+ if (sparse_option && sparse_file_p (stat))
+ {
+ status = sparse_dump_file (fd, stat);
+ if (status == dump_status_not_implemented)
+ status = dump_regular_file (fd, stat);
+ }
+ else
+ status = dump_regular_file (fd, stat);
+
+ switch (status)
+ {
+ case dump_status_ok:
+ if (multi_volume_option)
+ assign_string (&save_name, 0);
+ dump_regular_finish (fd, stat, original_ctime);
+ break;
+
+ case dump_status_short:
+ if (multi_volume_option)
+ assign_string (&save_name, 0);
+ close (fd);
+ break;
+
+ case dump_status_fail:
+ close (fd);
+ return;
+
+ case dump_status_not_implemented:
+ abort ();
+ }
+
+ if (atime_preserve_option)
+ utime (stat->orig_file_name, &restore_times);
+ file_count_links (stat);
+ return;
+ }
+#ifdef HAVE_READLINK
+ else if (S_ISLNK (stat->stat.st_mode))
+ {
+ char *buffer;
+ int size;
+ size_t linklen = stat->stat.st_size;
+ if (linklen != stat->stat.st_size || linklen + 1 == 0)
+ xalloc_die ();
+ buffer = (char *) alloca (linklen + 1);
+ size = readlink (p, buffer, linklen + 1);
+ if (size < 0)
+ {
+ readlink_diag (p);
+ return;
+ }
+ buffer[size] = '\0';
+ assign_string (&stat->link_name, buffer);
+ if (size > NAME_FIELD_SIZE)
+ write_long_link (stat);
+
+ block_ordinal = current_block_ordinal ();
+ stat->stat.st_size = 0; /* force 0 size on symlink */
+ header = start_header (stat);
+ if (!header)
+ return;
+ tar_copy_str (header->header.linkname, buffer, NAME_FIELD_SIZE);
+ header->header.typeflag = SYMTYPE;
+ finish_header (stat, header, block_ordinal);
+ /* nothing more to do to it */
+
+ if (remove_files_option)
+ {
+ if (unlink (p) == -1)
+ unlink_error (p);
+ }
+ file_count_links (stat);
+ return;
+ }
+#endif
+ else if (S_ISCHR (stat->stat.st_mode))
+ type = CHRTYPE;
+ else if (S_ISBLK (stat->stat.st_mode))
+ type = BLKTYPE;
+ else if (S_ISFIFO (stat->stat.st_mode))
+ type = FIFOTYPE;
+ else if (S_ISSOCK (stat->stat.st_mode))
+ {
+ WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
+ return;
+ }
+ else if (S_ISDOOR (stat->stat.st_mode))
+ {
+ WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
+ return;
+ }
+ else
+ {
+ unknown_file_error (p);
+ return;
+ }
+ }
+
+ if (archive_format == V7_FORMAT)
+ {
+ unknown_file_error (p);
+ return;
+ }
+
+ block_ordinal = current_block_ordinal ();
+ stat->stat.st_size = 0; /* force 0 size */
+ header = start_header (stat);
+ if (!header)
+ return;
+ header->header.typeflag = type;
+
+ if (type != FIFOTYPE)
+ {
+ MAJOR_TO_CHARS (major (stat->stat.st_rdev),
+ header->header.devmajor);
+ MINOR_TO_CHARS (minor (stat->stat.st_rdev),
+ header->header.devminor);
+ }
+
+ finish_header (stat, header, block_ordinal);
+ if (remove_files_option)
+ {
+ if (unlink (p) == -1)
+ unlink_error (p);
+ }