*** empty log message ***
[debian/tar] / src / update.c
1 /* Update a tar archive.
2    Copyright (C) 1988, 1992 Free Software Foundation
3
4 This file is part of GNU Tar.
5
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /* JF implement the 'r' 'u' and 'A' options for tar. */
21 /* The 'A' option is my own invention:  It means that the file-names are
22    tar files, and they should simply be appended to the end of the archive.
23    No attempt is made to block the reads from the args; if they're on raw
24    tape or something like that, it'll probably lose. . . */
25
26 #include <sys/types.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #ifndef STDC_HEADERS
30 extern int errno;
31 #endif
32
33 #ifdef HAVE_SYS_MTIO_H
34 #include <sys/ioctl.h>
35 #include <sys/mtio.h>
36 #endif
37
38 #ifdef BSD42
39 #include <sys/file.h>
40 #else
41 #ifndef V7
42 #include <fcntl.h>
43 #endif
44 #endif
45
46 #ifndef __MSDOS__
47 #include <pwd.h>
48 #include <grp.h>
49 #endif
50
51 #define STDIN 0
52 #define STDOUT 1
53
54 #include "tar.h"
55 #include "port.h"
56 #include "rmt.h"
57
58 int time_to_start_writing = 0;  /* We've hit the end of the old stuff,
59                                    and its time to start writing new stuff
60                                    to the tape.  This involves seeking
61                                    back one block and re-writing the current
62                                    block (which has been changed). */
63
64 char *output_start;             /* Pointer to where we started to write in
65                                    the first block we write out.  This is used
66                                    if we can't backspace the output and have
67                                    to null out the first part of the block */
68
69 extern void skip_file ();
70 extern void skip_extended_headers ();
71
72 extern union record *head;
73 extern struct stat hstat;
74
75 void append_file ();
76 void close_archive ();
77 int confirm ();
78 void decode_header ();
79 void fl_read ();
80 void fl_write ();
81 void flush_archive ();
82 int move_arch ();
83 struct name *name_scan ();
84 char *name_from_list ();
85 void name_expand ();
86 void name_gather ();
87 void names_notfound ();
88 void open_archive ();
89 int read_header ();
90 void reset_eof ();
91 void write_block ();
92 void write_eot ();
93
94 /* Implement the 'r' (add files to end of archive), and 'u' (add files to
95    end of archive if they arent there, or are more up to date than the
96    version in the archive.) commands.*/
97 void
98 update_archive ()
99 {
100   int found_end = 0;
101   int status = 3;
102   int prev_status;
103   char *p;
104   struct name *name;
105   extern void dump_file ();
106
107   name_gather ();
108   if (cmd_mode == CMD_UPDATE)
109     name_expand ();
110   open_archive (2);             /* Open for updating */
111
112   do
113     {
114       prev_status = status;
115       status = read_header ();
116       switch (status)
117         {
118         case EOF:
119           found_end = 1;
120           break;
121
122         case 0:         /* A bad record */
123           userec (head);
124           switch (prev_status)
125             {
126             case 3:
127               msg ("This doesn't look like a tar archive.");
128               /* FALL THROUGH */
129             case 2:
130             case 1:
131               msg ("Skipping to next header");
132             case 0:
133               break;
134             }
135           break;
136
137           /* A good record */
138         case 1:
139           /* printf("File %s\n",head->header.name); */
140           /* head->header.name[NAMSIZ-1]='\0'; */
141           if (cmd_mode == CMD_UPDATE && (name = name_scan (current_file_name)))
142             {
143
144               /* struct stat hstat; */
145               struct stat nstat;
146               int head_standard;
147
148               decode_header (head, &hstat, &head_standard, 0);
149               if (stat (current_file_name, &nstat) < 0)
150                 {
151                   msg_perror ("can't stat %s:", current_file_name);
152                 }
153               else
154                 {
155                   if (hstat.st_mtime >= nstat.st_mtime)
156                     name->found++;
157                 }
158             }
159           userec (head);
160           if (head->header.isextended)
161             skip_extended_headers ();
162           skip_file ((long) hstat.st_size);
163           break;
164
165         case 2:
166           ar_record = head;
167           found_end = 1;
168           break;
169         }
170     }
171   while (!found_end);
172
173   reset_eof ();
174   time_to_start_writing = 1;
175   output_start = ar_record->charptr;
176
177   while (p = name_from_list ())
178     {
179       if (f_confirm && !confirm ("add", p))
180         continue;
181       if (cmd_mode == CMD_CAT)
182         append_file (p);
183       else
184         dump_file (p, -1, 1);
185     }
186
187   write_eot ();
188   close_archive ();
189   names_notfound ();
190 }
191
192 /* Catenate file p to the archive without creating a header for it.  It had
193    better be a tar file or the archive is screwed */
194
195 void
196 append_file (p)
197      char *p;
198 {
199   int fd;
200   struct stat statbuf;
201   long bytes_left;
202   union record *start;
203   long bufsiz, count;
204
205   if (0 != stat (p, &statbuf) || (fd = open (p, O_RDONLY | O_BINARY)) < 0)
206     {
207       msg_perror ("can't open file %s", p);
208       errors++;
209       return;
210     }
211
212   bytes_left = statbuf.st_size;
213
214   while (bytes_left > 0)
215     {
216       start = findrec ();
217       bufsiz = endofrecs ()->charptr - start->charptr;
218       if (bytes_left < bufsiz)
219         {
220           bufsiz = bytes_left;
221           count = bufsiz % RECORDSIZE;
222           if (count)
223             bzero (start->charptr + bytes_left, (int) (RECORDSIZE - count));
224         }
225       count = read (fd, start->charptr, bufsiz);
226       if (count < 0)
227         {
228           msg_perror ("read error at byte %ld reading %d bytes in file %s", statbuf.st_size - bytes_left, bufsiz, p);
229           exit (EX_ARGSBAD);    /* FOO */
230         }
231       bytes_left -= count;
232       userec (start + (count - 1) / RECORDSIZE);
233       if (count != bufsiz)
234         {
235           msg ("%s: file shrunk by %d bytes, yark!", p, bytes_left);
236           abort ();
237         }
238     }
239   (void) close (fd);
240 }
241
242 #ifdef DONTDEF
243 bprint (fp, buf, num)
244      FILE *fp;
245      char *buf;
246 {
247   int c;
248
249   if (num == 0 || num == -1)
250     return;
251   fputs (" '", fp);
252   while (num--)
253     {
254       c = *buf++;
255       if (c == '\\')
256         fputs ("\\\\", fp);
257       else if (c >= ' ' && c <= '~')
258         putc (c, fp);
259       else
260         switch (c)
261           {
262           case '\n':
263             fputs ("\\n", fp);
264             break;
265           case '\r':
266             fputs ("\\r", fp);
267             break;
268           case '\b':
269             fputs ("\\b", fp);
270             break;
271           case '\0':
272             /* fputs("\\-",fp); */
273             break;
274           default:
275             fprintf (fp, "\\%03o", c);
276             break;
277           }
278     }
279   fputs ("'\n", fp);
280 }
281
282 #endif
283
284 int number_of_blocks_read = 0;
285
286 int number_of_new_records = 0;
287 int number_of_records_needed = 0;
288
289 union record *new_block = 0;
290 union record *save_block = 0;
291
292 void
293 junk_archive ()
294 {
295   int found_stuff = 0;
296   int status = 3;
297   int prev_status;
298   struct name *name;
299
300   /* int dummy_head; */
301   int number_of_records_to_skip = 0;
302   int number_of_records_to_keep = 0;
303   int number_of_kept_records_in_block;
304   int sub_status;
305   extern int write_archive_to_stdout;
306
307   /* fprintf(stderr,"Junk files\n"); */
308   name_gather ();
309   open_archive (2);
310
311   while (!found_stuff)
312     {
313       prev_status = status;
314       status = read_header ();
315       switch (status)
316         {
317         case EOF:
318           found_stuff = 1;
319           break;
320
321         case 0:
322           userec (head);
323           switch (prev_status)
324             {
325             case 3:
326               msg ("This doesn't look like a tar archive.");
327               /* FALL THROUGH */
328             case 2:
329             case 1:
330               msg ("Skipping to next header");
331               /* FALL THROUGH */
332             case 0:
333               break;
334             }
335           break;
336
337         case 1:
338           /* head->header.name[NAMSIZ-1] = '\0'; */
339           /* fprintf(stderr,"file %s\n",head->header.name); */
340           if ((name = name_scan (current_file_name)) == (struct name *) 0)
341             {
342               userec (head);
343               /* fprintf(stderr,"Skip %ld\n",(long)(hstat.st_size)); */
344               if (head->header.isextended)
345                 skip_extended_headers ();
346               skip_file ((long) (hstat.st_size));
347               break;
348             }
349           name->found = 1;
350           found_stuff = 2;
351           break;
352
353         case 2:
354           found_stuff = 1;
355           break;
356         }
357     }
358   /* fprintf(stderr,"Out of first loop\n"); */
359
360   if (found_stuff != 2)
361     {
362       write_eot ();
363       close_archive ();
364       names_notfound ();
365       return;
366     }
367
368   if (write_archive_to_stdout)
369     write_archive_to_stdout = 0;
370   new_block = (union record *) malloc (blocksize);
371   if (new_block == 0)
372     {
373       msg ("Can't allocate secondary block of %d bytes", blocksize);
374       exit (EX_SYSTEM);
375     }
376
377   /* Save away records before this one in this block */
378   number_of_new_records = ar_record - ar_block;
379   number_of_records_needed = blocking - number_of_new_records;
380   if (number_of_new_records)
381     bcopy ((void *) ar_block, (void *) new_block, (number_of_new_records) * RECORDSIZE);
382
383   /* fprintf(stderr,"Saved %d recs, need %d more\n",number_of_new_records,number_of_records_needed); */
384   userec (head);
385   if (head->header.isextended)
386     skip_extended_headers ();
387   skip_file ((long) (hstat.st_size));
388   found_stuff = 0;
389   /* goto flush_file; */
390
391   for (;;)
392     {
393       /* Fill in a block */
394       /* another_file: */
395       if (ar_record == ar_last)
396         {
397           /* fprintf(stderr,"New block\n"); */
398           flush_archive ();
399           number_of_blocks_read++;
400         }
401       sub_status = read_header ();
402       /* fprintf(stderr,"Header type %d\n",sub_status); */
403
404       if (sub_status == 2 && f_ignorez)
405         {
406           userec (head);
407           continue;
408         }
409       if (sub_status == EOF || sub_status == 2)
410         {
411           found_stuff = 1;
412           bzero (new_block[number_of_new_records].charptr, RECORDSIZE * number_of_records_needed);
413           number_of_new_records += number_of_records_needed;
414           number_of_records_needed = 0;
415           write_block (0);
416           break;
417         }
418
419       if (sub_status == 0)
420         {
421           msg ("Deleting non-header from archive.");
422           userec (head);
423           continue;
424         }
425
426       /* Found another header.  Yipee! */
427       /* head->header.name[NAMSIZ-1] = '\0'; */
428       /* fprintf(stderr,"File %s ",head->header.name); */
429       if (name = name_scan (current_file_name))
430         {
431           name->found = 1;
432           /* fprintf(stderr,"Flush it\n"); */
433           /* flush_file: */
434           /* decode_header(head,&hstat,&dummy_head,0); */
435           userec (head);
436           number_of_records_to_skip = (hstat.st_size + RECORDSIZE - 1) / RECORDSIZE;
437           /* fprintf(stderr,"Flushing %d recs from %s\n",number_of_records_to_skip,head->header.name); */
438
439           while (ar_last - ar_record <= number_of_records_to_skip)
440             {
441
442               /* fprintf(stderr,"Block: %d <= %d  ",ar_last-ar_record,number_of_records_to_skip); */
443               number_of_records_to_skip -= (ar_last - ar_record);
444               flush_archive ();
445               number_of_blocks_read++;
446               /* fprintf(stderr,"Block %d left\n",number_of_records_to_skip); */
447             }
448           ar_record += number_of_records_to_skip;
449           /* fprintf(stderr,"Final %d\n",number_of_records_to_skip); */
450           number_of_records_to_skip = 0;
451           continue;
452         }
453
454       /* copy_header: */
455       new_block[number_of_new_records] = *head;
456       number_of_new_records++;
457       number_of_records_needed--;
458       number_of_records_to_keep = (hstat.st_size + RECORDSIZE - 1) / RECORDSIZE;
459       userec (head);
460       if (number_of_records_needed == 0)
461         write_block (1);
462       /* copy_data: */
463       number_of_kept_records_in_block = ar_last - ar_record;
464       if (number_of_kept_records_in_block > number_of_records_to_keep)
465         number_of_kept_records_in_block = number_of_records_to_keep;
466
467       /* fprintf(stderr,"Need %d kept_in %d keep %d\n",blocking,number_of_kept_records_in_block,number_of_records_to_keep); */
468
469       while (number_of_records_to_keep)
470         {
471           int n;
472
473           if (ar_record == ar_last)
474             {
475               /* fprintf(stderr,"Flush. . .\n"); */
476               fl_read ();
477               number_of_blocks_read++;
478               ar_record = ar_block;
479               number_of_kept_records_in_block = blocking;
480               if (number_of_kept_records_in_block > number_of_records_to_keep)
481                 number_of_kept_records_in_block = number_of_records_to_keep;
482             }
483           n = number_of_kept_records_in_block;
484           if (n > number_of_records_needed)
485             n = number_of_records_needed;
486
487           /* fprintf(stderr,"Copying %d\n",n); */
488           bcopy ((void *) ar_record, (void *) (new_block + number_of_new_records), n * RECORDSIZE);
489           number_of_new_records += n;
490           number_of_records_needed -= n;
491           ar_record += n;
492           number_of_records_to_keep -= n;
493           number_of_kept_records_in_block -= n;
494           /* fprintf(stderr,"Now new %d  need %d  keep %d  keep_in %d rec %d/%d\n",
495  number_of_new_records,number_of_records_needed,number_of_records_to_keep,
496  number_of_kept_records_in_block,ar_record-ar_block,ar_last-ar_block); */
497
498           if (number_of_records_needed == 0)
499             {
500               write_block (1);
501             }
502         }
503     }
504
505   write_eot ();
506   close_archive ();
507   names_notfound ();
508 }
509
510 void
511 write_block (f)
512      int f;
513 {
514   /* fprintf(stderr,"Write block\n"); */
515   /* We've filled out a block.  Write it out. */
516
517   /* Backspace back to where we started. . . */
518   if (archive != STDIN)
519     (void) move_arch (-(number_of_blocks_read + 1));
520
521   save_block = ar_block;
522   ar_block = new_block;
523
524   if (archive == STDIN)
525     archive = STDOUT;
526   fl_write ();
527
528   if (archive == STDOUT)
529     archive = STDIN;
530   ar_block = save_block;
531
532   if (f)
533     {
534       /* Move the tape head back to where we were */
535       if (archive != STDIN)
536         (void) move_arch (number_of_blocks_read);
537       number_of_blocks_read--;
538     }
539
540   number_of_records_needed = blocking;
541   number_of_new_records = 0;
542 }
543
544 /* Move archive descriptor by n blocks worth.  If n is positive we move
545    forward, else we move negative.   If its a tape, MTIOCTOP had better
546    work.  If its something else, we try to seek on it.  If we can't
547    seek, we lose! */
548 int
549 move_arch (n)
550      int n;
551 {
552   long cur;
553
554 #ifdef MTIOCTOP
555   struct mtop t;
556   int er;
557
558   if (n > 0)
559     {
560       t.mt_op = MTFSR;
561       t.mt_count = n;
562     }
563   else
564     {
565       t.mt_op = MTBSR;
566       t.mt_count = -n;
567     }
568   if ((er = rmtioctl (archive, MTIOCTOP, &t)) >= 0)
569     return 1;
570   if (errno == EIO && (er = rmtioctl (archive, MTIOCTOP, &t)) >= 0)
571     return 1;
572 #endif
573
574   cur = rmtlseek (archive, 0L, 1);
575   cur += blocksize * n;
576
577   /* fprintf(stderr,"Fore to %x\n",cur); */
578   if (rmtlseek (archive, cur, 0) != cur)
579     {
580       /* Lseek failed.  Try a different method */
581       msg ("Couldn't re-position archive file.");
582       exit (EX_BADARCH);
583     }
584   return 3;
585 }