]> Dogcows Code - chaz/tar/blobdiff - src/update.c
Fix some problems with negative and out-of-range integers.
[chaz/tar] / src / update.c
index 6546b03169eaa55497cb40f12dda9cd45b374388..17f9e052047e91859f3afc29da8132d09cf6bd64 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, 2005 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
@@ -47,7 +47,7 @@ char *output_start;
 static void
 append_file (char *file_name)
 {
 static void
 append_file (char *file_name)
 {
-  int handle = open (file_name, O_RDONLY | O_BINARY);
+  int handle = openat (chdir_fd, file_name, O_RDONLY | O_BINARY);
   struct stat stat_data;
 
   if (handle < 0)
   struct stat stat_data;
 
   if (handle < 0)
@@ -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)
        {
@@ -128,6 +130,8 @@ update_archive (void)
 
            decode_header (current_header, &current_stat_info,
                           &current_format, 0);
 
            decode_header (current_header, &current_stat_info,
                           &current_format, 0);
+           transform_stat_info (current_header->header.typeflag,
+                                &current_stat_info);
            archive_format = current_format;
 
            if (subcommand_option == UPDATE_SUBCOMMAND
            archive_format = current_format;
 
            if (subcommand_option == UPDATE_SUBCOMMAND
@@ -136,12 +140,43 @@ update_archive (void)
                struct stat s;
 
                chdir_do (name->change_dir);
                struct stat s;
 
                chdir_do (name->change_dir);
-               if (deref_stat (dereference_option,
-                               current_stat_info.file_name, &s) == 0
-                   && (tar_timespec_cmp (get_stat_mtime (&s),
-                                         current_stat_info.mtime)
-                       <= 0))
-                 add_avoided_name (current_stat_info.file_name);
+               if (deref_stat (current_stat_info.file_name, &s) == 0)
+                 {
+                   if (S_ISDIR (s.st_mode))
+                     {
+                       char *p, *dirp;
+                       DIR *stream = NULL;
+                       int fd = openat (chdir_fd, name->name,
+                                        open_read_flags | O_DIRECTORY);
+                       if (fd < 0)
+                         open_error (name->name);
+                       else if (! ((stream = fdopendir (fd))
+                                   && (dirp = streamsavedir (stream))))
+                         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);
+                         }
+
+                       if (stream
+                           ? closedir (stream) != 0
+                           : 0 <= fd && close (fd) != 0)
+                         savedir_error (name->name);
+                     }
+                   else if (tar_timespec_cmp (get_stat_mtime (&s),
+                                              current_stat_info.mtime)
+                            <= 0)
+                     remname (name);
+                 }
              }
 
            skip_member ();
              }
 
            skip_member ();
@@ -181,7 +216,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 +224,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 +235,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.031015 seconds and 4 git commands to generate.