]> Dogcows Code - chaz/tar/blobdiff - src/update.c
tar: more reliable directory traversal when creating archives
[chaz/tar] / src / update.c
index f28c6dc3f3ca0a7e9c9c39852689fe03161607a2..53ce553b0ca680944ae0a33b6d08126369c1752e 100644 (file)
@@ -1,11 +1,11 @@
 /* Update a tar archive.
 
    Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
 /* Update a tar archive.
 
    Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
-   2004 Free Software Foundation, Inc.
+   2004, 2005, 2007, 2010 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any later
+   Free Software Foundation; either version 3, or (at your option) any later
    version.
 
    This program is distributed in the hope that it will be useful, but
    version.
 
    This program is distributed in the hope that it will be useful, but
@@ -110,11 +110,13 @@ update_archive (void)
 
   name_gather ();
   open_archive (ACCESS_UPDATE);
 
   name_gather ();
   open_archive (ACCESS_UPDATE);
-  xheader_write_global ();
+  buffer_write_global_xheader ();
 
   while (!found_end)
     {
 
   while (!found_end)
     {
-      enum read_header status = read_header (false);
+      enum read_header status = read_header (&current_header,
+                                             &current_stat_info,
+                                             read_header_auto);
 
       switch (status)
        {
 
       switch (status)
        {
@@ -137,11 +139,33 @@ update_archive (void)
 
                chdir_do (name->change_dir);
                if (deref_stat (dereference_option,
 
                chdir_do (name->change_dir);
                if (deref_stat (dereference_option,
-                               current_stat_info.file_name, &s) == 0
-                   && (timespec_cmp (get_stat_mtime (&s),
-                                     current_stat_info.mtime)
-                       <= 0))
-                 add_avoided_name (current_stat_info.file_name);
+                               current_stat_info.file_name, &s) == 0)
+                 {
+                   if (S_ISDIR (s.st_mode))
+                     {
+                       char *p, *dirp;
+                       dirp = savedir (name->name);
+                       if (!dirp)
+                         savedir_error (name->name);
+                       else
+                         {
+                           namebuf_t nbuf = namebuf_create (name->name);
+
+                           for (p = dirp; *p; p += strlen (p) + 1)
+                             addname (namebuf_name (nbuf, p),
+                                      0, false, NULL);
+
+                           namebuf_free (nbuf);
+                           free (dirp);
+
+                           remname (name);
+                         }
+                     }
+                   else if (tar_timespec_cmp (get_stat_mtime (&s),
+                                              current_stat_info.mtime)
+                            <= 0)
+                     remname (name);
+                 }
              }
 
            skip_member ();
              }
 
            skip_member ();
@@ -181,7 +205,6 @@ update_archive (void)
        }
 
       tar_stat_destroy (&current_stat_info);
        }
 
       tar_stat_destroy (&current_stat_info);
-      xheader_destroy (&extended_header);
       previous_status = status;
     }
 
       previous_status = status;
     }
 
@@ -190,10 +213,10 @@ update_archive (void)
   output_start = current_block->buffer;
 
   {
   output_start = current_block->buffer;
 
   {
-    char *file_name;
-
-    while ((file_name = name_from_list ()) != NULL)
+    struct name const *p;
+    while ((p = name_from_list ()) != NULL)
       {
       {
+       char *file_name = p->name;
        if (excluded_name (file_name))
          continue;
        if (interactive_option && !confirm ("add", file_name))
        if (excluded_name (file_name))
          continue;
        if (interactive_option && !confirm ("add", file_name))
@@ -201,11 +224,12 @@ update_archive (void)
        if (subcommand_option == CAT_SUBCOMMAND)
          append_file (file_name);
        else
        if (subcommand_option == CAT_SUBCOMMAND)
          append_file (file_name);
        else
-         dump_file (file_name, 1, (dev_t) 0);
+         dump_file (0, file_name, file_name);
       }
   }
 
   write_eot ();
   close_archive ();
       }
   }
 
   write_eot ();
   close_archive ();
+  finish_deferred_unlinks ();
   names_notfound ();
 }
   names_notfound ();
 }
This page took 0.027428 seconds and 4 git commands to generate.