- blank_name_list ();
- while (p = name_from_list (), p)
- if (!excluded_name (p))
- {
- strcpy (buffer, p);
- if (p[strlen (p) - 1] != '/')
- strcat (buffer, "/");
- bufp = buffer + strlen (buffer);
- q = gnu_list_name->dir_contents;
- if (q)
- for (; *q; q += strlen (q) + 1)
- if (*q == 'Y')
- {
- strcpy (bufp, q + 1);
- dump_file (buffer, -1, (dev_t) 0);
- }
- }
- free (buffer);
- }
- else
- {
- while (p = name_next (1), p)
- if (!excluded_name (p))
- dump_file (p, 1, (dev_t) 0);
- }
-
- write_eot ();
- close_archive ();
-
- if (listed_incremental_option)
- write_directory_file ();
-}
-
-/* Dump a single file, recursing on directories. P is the file name
- to dump. TOP_LEVEL tells whether this is a top-level call; zero
- means no, positive means yes, and negative means an incremental
- dump. PARENT_DEVICE is the device of P's
- parent directory; it is examined only if TOP_LEVEL is zero.
-
- Set global CURRENT_STAT to stat output for this file. */
-
-/* FIXME: One should make sure that for *every* path leading to setting
- exit_status to failure, a clear diagnostic has been issued. */
-
-void
-dump_file (char *p, int top_level, dev_t parent_device)
-{
- union block *header;
- char type;
- union block *exhdr;
- char save_typeflag;
- time_t original_ctime;
- struct utimbuf restore_times;
-
- /* FIXME: `header' and `upperbound' might be used uninitialized in this
- function. Reported by Bruno Haible. */
-
- if (interactive_option && !confirm ("add", p))
- return;
-
- if (deref_stat (dereference_option, p, ¤t_stat) != 0)
- {
- WARN ((0, errno, _("Cannot add file %s"), p));
- if (!ignore_failed_read_option)
- exit_status = TAREXIT_FAILURE;
- return;
- }
-
- original_ctime = current_stat.st_ctime;
- restore_times.actime = current_stat.st_atime;
- restore_times.modtime = current_stat.st_mtime;
-
-#ifdef S_ISHIDDEN
- if (S_ISHIDDEN (current_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 (current_stat.st_mode)
- && current_stat.st_mtime < newer_mtime_option
- && (!after_date_option || current_stat.st_ctime < newer_ctime_option))
- {
- if (0 < top_level)
- WARN ((0, 0, _("%s: is unchanged; not dumped"), p));
- /* FIXME: recheck this return. */
- return;
- }
-
-#if !MSDOS
- /* See if we are trying to dump the archive. */
-
- if (ar_dev && current_stat.st_dev == ar_dev && current_stat.st_ino == ar_ino)
- {
- WARN ((0, 0, _("%s is the archive; not dumped"), p));
- return;
- }
-#endif
-
- if (S_ISDIR (current_stat.st_mode))
- {
- DIR *directory;
- struct dirent *entry;
- char *namebuf;
- size_t buflen;
- size_t len;
- dev_t our_device = current_stat.st_dev;
-
- /* If this tar program is installed suid root, like for Amanda, the
- access might look like denied, while it is not really.
-
- FIXME: I have the feeling this test is done too early. Couldn't it
- just be bundled in later actions? I guess that the proper support
- of --ignore-failed-read is the key of the current writing. */
-
- if (access (p, R_OK) == -1 && geteuid () != 0)
- {
- WARN ((0, errno, _("Cannot add directory %s"), p));
- if (!ignore_failed_read_option)
- exit_status = TAREXIT_FAILURE;
- return;
- }
-
- /* Build new prototype name. Ensure exactly one trailing slash. */
-
- len = strlen (p);
- buflen = len + NAME_FIELD_SIZE;
- namebuf = xmalloc (buflen + 1);
- strncpy (namebuf, p, buflen);
- while (len >= 1 && namebuf[len - 1] == '/')
- len--;
- namebuf[len++] = '/';
- namebuf[len] = '\0';
-
- if (! is_avoided_name (namebuf))
- {
- /* The condition above used to be "archive_format != V7_FORMAT".
- GNU tar was not writing directory blocks at all. Daniel Trinkle
- writes: ``All old versions of tar I have ever seen have
- correctly archived an empty directory. The really old ones I
- checked included HP-UX 7 and Mt. Xinu More/BSD. There may be
- some subtle reason for the exclusion that I don't know, but the
- current behavior is broken.'' I do not know those subtle
- reasons either, so until these are reported (anew?), just allow
- directory blocks to be written even with old archives. */
-
- current_stat.st_size = 0; /* force 0 size on dir */
-
- /* FIXME: If people could really read standard archives, this
- should be:
-
- header
- = start_header (standard_option ? p : namebuf, ¤t_stat);
-
- but since they'd interpret DIRTYPE blocks as regular
- files, we'd better put the / on the name. */
-
- header = start_header (namebuf, ¤t_stat);