1 /* Update a tar archive.
2 Copyright (C) 1988, 1992 Free Software Foundation
4 This file is part of GNU Tar.
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)
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.
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. */
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. . . */
26 #include <sys/types.h>
34 #include <sys/ioctl.h>
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). */
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 */
69 extern void skip_file();
70 extern void skip_extended_headers();
72 extern union record
*head
;
73 extern struct stat hstat
;
83 struct name
*name_scan();
84 char *name_from_list();
87 void names_notfound();
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.*/
105 extern void dump_file();
108 if(cmd_mode
==CMD_UPDATE
)
110 open_archive(2); /* Open for updating */
114 status
=read_header();
120 case 0: /* A bad record */
122 switch(prev_status
) {
124 msg("This doesn't look like a tar archive.");
128 msg("Skipping to next header");
136 /* printf("File %s\n",head->header.name); */
137 /* head->header.name[NAMSIZ-1]='\0'; */
138 if(cmd_mode
==CMD_UPDATE
&& (name
=name_scan(head
->header
.name
))) {
139 /* struct stat hstat; */
143 decode_header(head
,&hstat
,&head_standard
,0);
144 if(stat(head
->header
.name
,&nstat
)<0) {
145 msg_perror("can't stat %s:",head
->header
.name
);
147 if(hstat
.st_mtime
>=nstat
.st_mtime
)
152 if (head
->header
.isextended
)
153 skip_extended_headers();
154 skip_file((long)hstat
.st_size
);
165 time_to_start_writing
= 1;
166 output_start
=ar_record
->charptr
;
168 while(p
=name_from_list()) {
169 if(f_confirm
&& !confirm("add", p
))
171 if(cmd_mode
==CMD_CAT
)
182 /* Catenate file p to the archive without creating a header for it. It had
183 better be a tar file or the archive is screwed */
195 if(0 != stat(p
,&statbuf
) || (fd
=open(p
,O_RDONLY
|O_BINARY
))<0) {
196 msg_perror("can't open file %s",p
);
201 bytes_left
= statbuf
.st_size
;
203 while(bytes_left
>0) {
205 bufsiz
=endofrecs()->charptr
- start
->charptr
;
206 if(bytes_left
< bufsiz
) {
208 count
= bufsiz
% RECORDSIZE
;
210 bzero(start
->charptr
+ bytes_left
,(int)(RECORDSIZE
-count
));
212 count
=read(fd
,start
->charptr
,bufsiz
);
214 msg_perror("read error at byte %ld reading %d bytes in file %s",statbuf
.st_size
-bytes_left
,bufsiz
,p
);
215 exit(EX_ARGSBAD
); /* FOO */
218 userec(start
+(count
-1)/RECORDSIZE
);
220 msg("%s: file shrunk by %d bytes, yark!",p
,bytes_left
);
234 if(num
==0 || num
==-1)
239 if(c
=='\\') fputs("\\\\",fp
);
240 else if(c
>=' ' && c
<='~')
253 /* fputs("\\-",fp); */
256 fprintf(fp
,"\\%03o",c
);
264 int number_of_blocks_read
= 0;
266 int number_of_new_records
= 0;
267 int number_of_records_needed
= 0;
269 union record
*new_block
= 0;
270 union record
*save_block
= 0;
280 /* int dummy_head; */
281 int number_of_records_to_skip
= 0;
282 int number_of_records_to_keep
= 0;
283 int number_of_kept_records_in_block
;
285 extern int write_archive_to_stdout
;
287 /* fprintf(stderr,"Junk files\n"); */
291 while(!found_stuff
) {
293 status
=read_header();
301 switch(prev_status
) {
303 msg("This doesn't look like a tar archive.");
307 msg("Skipping to next header");
315 /* head->header.name[NAMSIZ-1] = '\0'; */
316 /* fprintf(stderr,"file %s\n",head->header.name); */
317 if((name
=name_scan(head
->header
.name
))==(struct name
*)0) {
319 /* fprintf(stderr,"Skip %ld\n",(long)(hstat.st_size)); */
320 if (head
->header
.isextended
)
321 skip_extended_headers();
322 skip_file((long)(hstat
.st_size
));
334 /* fprintf(stderr,"Out of first loop\n"); */
343 if(write_archive_to_stdout
)
344 write_archive_to_stdout
= 0;
345 new_block
= (union record
*)malloc(blocksize
);
347 msg("Can't allocate secondary block of %d bytes",blocksize
);
351 /* Save away records before this one in this block */
352 number_of_new_records
=ar_record
-ar_block
;
353 number_of_records_needed
= blocking
- number_of_new_records
;
354 if(number_of_new_records
)
355 bcopy((void *)ar_block
,(void *)new_block
,(number_of_new_records
)*RECORDSIZE
);
357 /* fprintf(stderr,"Saved %d recs, need %d more\n",number_of_new_records,number_of_records_needed); */
359 if (head
->header
.isextended
)
360 skip_extended_headers();
361 skip_file((long)(hstat
.st_size
));
363 /* goto flush_file; */
366 /* Fill in a block */
368 if(ar_record
==ar_last
) {
369 /* fprintf(stderr,"New block\n"); */
371 number_of_blocks_read
++;
373 sub_status
= read_header();
374 /* fprintf(stderr,"Header type %d\n",sub_status); */
376 if(sub_status
==2 && f_ignorez
) {
380 if(sub_status
==EOF
|| sub_status
==2) {
382 bzero(new_block
[number_of_new_records
].charptr
,RECORDSIZE
*number_of_records_needed
);
383 number_of_new_records
+=number_of_records_needed
;
384 number_of_records_needed
= 0;
390 msg("Deleting non-header from archive.");
395 /* Found another header. Yipee! */
396 /* head->header.name[NAMSIZ-1] = '\0'; */
397 /* fprintf(stderr,"File %s ",head->header.name); */
398 if(name
=name_scan(head
->header
.name
)) {
400 /* fprintf(stderr,"Flush it\n"); */
402 /* decode_header(head,&hstat,&dummy_head,0); */
404 number_of_records_to_skip
=(hstat
.st_size
+RECORDSIZE
-1)/RECORDSIZE
;
405 /* fprintf(stderr,"Flushing %d recs from %s\n",number_of_records_to_skip,head->header.name); */
407 while(ar_last
-ar_record
<=number_of_records_to_skip
) {
409 /* fprintf(stderr,"Block: %d <= %d ",ar_last-ar_record,number_of_records_to_skip); */
410 number_of_records_to_skip
-= (ar_last
- ar_record
);
412 number_of_blocks_read
++;
413 /* fprintf(stderr,"Block %d left\n",number_of_records_to_skip); */
415 ar_record
+=number_of_records_to_skip
;
416 /* fprintf(stderr,"Final %d\n",number_of_records_to_skip); */
417 number_of_records_to_skip
= 0;
422 new_block
[number_of_new_records
]= *head
;
423 number_of_new_records
++;
424 number_of_records_needed
--;
425 number_of_records_to_keep
=(hstat
.st_size
+RECORDSIZE
-1)/RECORDSIZE
;
427 if(number_of_records_needed
==0)
430 number_of_kept_records_in_block
= ar_last
- ar_record
;
431 if(number_of_kept_records_in_block
> number_of_records_to_keep
)
432 number_of_kept_records_in_block
= number_of_records_to_keep
;
434 /* fprintf(stderr,"Need %d kept_in %d keep %d\n",blocking,number_of_kept_records_in_block,number_of_records_to_keep); */
436 while(number_of_records_to_keep
) {
439 if(ar_record
==ar_last
) {
440 /* fprintf(stderr,"Flush. . .\n"); */
442 number_of_blocks_read
++;
444 number_of_kept_records_in_block
= blocking
;
445 if(number_of_kept_records_in_block
> number_of_records_to_keep
)
446 number_of_kept_records_in_block
= number_of_records_to_keep
;
448 n
= number_of_kept_records_in_block
;
449 if(n
>number_of_records_needed
)
450 n
= number_of_records_needed
;
452 /* fprintf(stderr,"Copying %d\n",n); */
453 bcopy((void *)ar_record
, (void *)(new_block
+number_of_new_records
), n
*RECORDSIZE
);
454 number_of_new_records
+= n
;
455 number_of_records_needed
-= n
;
457 number_of_records_to_keep
-= n
;
458 number_of_kept_records_in_block
-= n
;
459 /* fprintf(stderr,"Now new %d need %d keep %d keep_in %d rec %d/%d\n",
460 number_of_new_records,number_of_records_needed,number_of_records_to_keep,
461 number_of_kept_records_in_block,ar_record-ar_block,ar_last-ar_block); */
463 if(number_of_records_needed
== 0) {
478 /* fprintf(stderr,"Write block\n"); */
479 /* We've filled out a block. Write it out. */
481 /* Backspace back to where we started. . . */
483 (void)move_arch(-(number_of_blocks_read
+1));
485 save_block
= ar_block
;
486 ar_block
= new_block
;
494 ar_block
= save_block
;
497 /* Move the tape head back to where we were */
499 (void)move_arch(number_of_blocks_read
);
500 number_of_blocks_read
--;
503 number_of_records_needed
= blocking
;
504 number_of_new_records
= 0;
507 /* Move archive descriptor by n blocks worth. If n is positive we move
508 forward, else we move negative. If its a tape, MTIOCTOP had better
509 work. If its something else, we try to seek on it. If we can't
528 if((er
=rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
530 if(errno
==EIO
&& (er
=rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
534 cur
=rmtlseek(archive
,0L,1);
537 /* fprintf(stderr,"Fore to %x\n",cur); */
538 if(rmtlseek(archive
,cur
,0)!=cur
) {
539 /* Lseek failed. Try a different method */
540 msg("Couldn't re-position archive file.");