X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fupdate.c;h=17f9e052047e91859f3afc29da8132d09cf6bd64;hb=df7b55a8f6354e30e8da62eec7f706df033d0c81;hp=6546b03169eaa55497cb40f12dda9cd45b374388;hpb=57c2124d68aa65843548feef9d226fb025503258;p=chaz%2Ftar diff --git a/src/update.c b/src/update.c index 6546b03..17f9e05 100644 --- a/src/update.c +++ b/src/update.c @@ -1,11 +1,11 @@ /* 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 - 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 @@ -47,7 +47,7 @@ char *output_start; 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) @@ -110,11 +110,13 @@ update_archive (void) name_gather (); open_archive (ACCESS_UPDATE); - xheader_write_global (); + buffer_write_global_xheader (); while (!found_end) { - enum read_header status = read_header (false); + enum read_header status = read_header (¤t_header, + ¤t_stat_info, + read_header_auto); switch (status) { @@ -128,6 +130,8 @@ update_archive (void) decode_header (current_header, ¤t_stat_info, ¤t_format, 0); + transform_stat_info (current_header->header.typeflag, + ¤t_stat_info); archive_format = current_format; if (subcommand_option == UPDATE_SUBCOMMAND @@ -136,12 +140,43 @@ update_archive (void) 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 (); @@ -181,7 +216,6 @@ update_archive (void) } tar_stat_destroy (¤t_stat_info); - xheader_destroy (&extended_header); previous_status = status; } @@ -190,10 +224,10 @@ update_archive (void) 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)) @@ -201,11 +235,12 @@ update_archive (void) 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 (); + finish_deferred_unlinks (); names_notfound (); }