(to_chars): Fix base-256 output.
[debian/tar] / src / update.c
1 /* Update a tar archive.
2    Copyright 1988, 1992, 1994, 1996, 1997, 1999 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify it
5    under the terms of the GNU General Public License as published by the
6    Free Software Foundation; either version 2, or (at your option) any later
7    version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
12    Public License for more details.
13
14    You should have received a copy of the GNU General Public License along
15    with this program; if not, write to the Free Software Foundation, Inc.,
16    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 /* Implement the 'r', 'u' and 'A' options for tar.  'A' means that the
19    file names are tar files, and they should simply be appended to the end
20    of the archive.  No attempt is made to record the reads from the args; if
21    they're on raw tape or something like that, it'll probably lose...  */
22
23 #include "system.h"
24 #include "common.h"
25
26 /* FIXME: This module should not directly handle the following variable,
27    instead, this should be done in buffer.c only.  */
28 extern union block *current_block;
29
30 /* We've hit the end of the old stuff, and its time to start writing new
31    stuff to the tape.  This involves seeking back one record and
32    re-writing the current record (which has been changed).  */
33 int time_to_start_writing;
34
35 /* Pointer to where we started to write in the first record we write out.
36    This is used if we can't backspace the output and have to null out the
37    first part of the record.  */
38 char *output_start;
39
40 /*------------------------------------------------------------------------.
41 | Catenate file PATH to the archive without creating a header for it.  It |
42 | had better be a tar file or the archive is screwed.                     |
43 `------------------------------------------------------------------------*/
44
45 static void
46 append_file (char *path)
47 {
48   int handle = open (path, O_RDONLY | O_BINARY);
49   struct stat stat_data;
50
51   if (handle < 0)
52     {
53       ERROR ((0, errno, _("Cannot open file %s"), path));
54       return;
55     }
56
57   if (fstat (handle, &stat_data) != 0)
58     ERROR ((0, errno, "%s", path));
59   else
60     {
61       off_t bytes_left = stat_data.st_size;
62
63       while (bytes_left > 0)
64         {
65           union block *start = find_next_block ();
66           size_t buffer_size = available_space_after (start);
67           ssize_t status;
68           char buf[UINTMAX_STRSIZE_BOUND];
69
70           if (bytes_left < buffer_size)
71             {
72               buffer_size = bytes_left;
73               status = buffer_size % BLOCKSIZE;
74               if (status)
75                 memset (start->buffer + bytes_left, 0, BLOCKSIZE - status);
76             }
77
78           status = safe_read (handle, start->buffer, buffer_size);
79           if (status < 0)
80             FATAL_ERROR ((0, errno,
81                           _("Read error at byte %s reading %lu bytes in file %s"),
82                           STRINGIFY_BIGINT (stat_data.st_size - bytes_left,
83                                             buf),
84                           (unsigned long) buffer_size, path));
85           if (status == 0)
86             FATAL_ERROR ((0, 0, _("%s: File shrunk by %s bytes, (yark!)"),
87                           path, STRINGIFY_BIGINT (bytes_left, buf)));
88
89           bytes_left -= status;
90
91           set_next_block_after (start + (status - 1) / BLOCKSIZE);
92         }
93     }
94
95   close (handle);
96 }
97
98 /*-----------------------------------------------------------------------.
99 | Implement the 'r' (add files to end of archive), and 'u' (add files to |
100 | end of archive if they arent there, or are more up to date than the    |
101 | version in the archive.) commands.                                     |
102 `-----------------------------------------------------------------------*/
103
104 void
105 update_archive (void)
106 {
107   enum read_header previous_status = HEADER_STILL_UNREAD;
108   int found_end = 0;
109
110   name_gather ();
111   open_archive (ACCESS_UPDATE);
112
113   while (!found_end)
114     {
115       enum read_header status = read_header ();
116
117       switch (status)
118         {
119         case HEADER_STILL_UNREAD:
120           abort ();
121
122         case HEADER_SUCCESS:
123           {
124             struct name *name;
125
126             if (subcommand_option == UPDATE_SUBCOMMAND
127                 && (name = name_scan (current_file_name), name))
128               {
129                 struct stat s;
130                 enum archive_format unused;
131
132                 decode_header (current_header, &current_stat, &unused, 0);
133                 chdir_do (name->change_dir);
134                 if (deref_stat (dereference_option, current_file_name, &s) == 0
135                     && s.st_mtime <= current_stat.st_mtime)
136                   add_avoided_name (current_file_name);
137               }
138             set_next_block_after (current_header);
139             if (current_header->oldgnu_header.isextended)
140               skip_extended_headers ();
141             skip_file (current_stat.st_size);
142             break;
143           }
144
145         case HEADER_ZERO_BLOCK:
146           current_block = current_header;
147           found_end = 1;
148           break;
149
150         case HEADER_END_OF_FILE:
151           found_end = 1;
152           break;
153
154         case HEADER_FAILURE:
155           set_next_block_after (current_header);
156           switch (previous_status)
157             {
158             case HEADER_STILL_UNREAD:
159               WARN ((0, 0, _("This does not look like a tar archive")));
160               /* Fall through.  */
161
162             case HEADER_SUCCESS:
163             case HEADER_ZERO_BLOCK:
164               ERROR ((0, 0, _("Skipping to next header")));
165               /* Fall through.  */
166
167             case HEADER_FAILURE:
168               break;
169
170             case HEADER_END_OF_FILE:
171               abort ();
172             }
173           break;
174         }
175
176       previous_status = status;
177     }
178
179   reset_eof ();
180   time_to_start_writing = 1;
181   output_start = current_block->buffer;
182
183   {
184     char *path;
185
186     while (path = name_from_list (), path)
187       {
188         if (excluded_name (path))
189           continue;
190         if (interactive_option && !confirm ("add", path))
191           continue;
192         if (subcommand_option == CAT_SUBCOMMAND)
193           append_file (path);
194         else
195           dump_file (path, (dev_t) 0, 1);
196       }
197   }
198
199   write_eot ();
200   close_archive ();
201   names_notfound ();
202 }