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>
33 #ifdef HAVE_SYS_MTIO_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(current_file_name
)))
141 /* struct stat hstat; */
145 decode_header(head
,&hstat
,&head_standard
,0);
146 if(stat(current_file_name
,&nstat
)<0) {
147 msg_perror("can't stat %s:",current_file_name
);
149 if(hstat
.st_mtime
>=nstat
.st_mtime
)
154 if (head
->header
.isextended
)
155 skip_extended_headers();
156 skip_file((long)hstat
.st_size
);
167 time_to_start_writing
= 1;
168 output_start
=ar_record
->charptr
;
170 while(p
=name_from_list()) {
171 if(f_confirm
&& !confirm("add", p
))
173 if(cmd_mode
==CMD_CAT
)
184 /* Catenate file p to the archive without creating a header for it. It had
185 better be a tar file or the archive is screwed */
197 if(0 != stat(p
,&statbuf
) || (fd
=open(p
,O_RDONLY
|O_BINARY
))<0) {
198 msg_perror("can't open file %s",p
);
203 bytes_left
= statbuf
.st_size
;
205 while(bytes_left
>0) {
207 bufsiz
=endofrecs()->charptr
- start
->charptr
;
208 if(bytes_left
< bufsiz
) {
210 count
= bufsiz
% RECORDSIZE
;
212 bzero(start
->charptr
+ bytes_left
,(int)(RECORDSIZE
-count
));
214 count
=read(fd
,start
->charptr
,bufsiz
);
216 msg_perror("read error at byte %ld reading %d bytes in file %s",statbuf
.st_size
-bytes_left
,bufsiz
,p
);
217 exit(EX_ARGSBAD
); /* FOO */
220 userec(start
+(count
-1)/RECORDSIZE
);
222 msg("%s: file shrunk by %d bytes, yark!",p
,bytes_left
);
236 if(num
==0 || num
==-1)
241 if(c
=='\\') fputs("\\\\",fp
);
242 else if(c
>=' ' && c
<='~')
255 /* fputs("\\-",fp); */
258 fprintf(fp
,"\\%03o",c
);
266 int number_of_blocks_read
= 0;
268 int number_of_new_records
= 0;
269 int number_of_records_needed
= 0;
271 union record
*new_block
= 0;
272 union record
*save_block
= 0;
282 /* int dummy_head; */
283 int number_of_records_to_skip
= 0;
284 int number_of_records_to_keep
= 0;
285 int number_of_kept_records_in_block
;
287 extern int write_archive_to_stdout
;
289 /* fprintf(stderr,"Junk files\n"); */
293 while(!found_stuff
) {
295 status
=read_header();
303 switch(prev_status
) {
305 msg("This doesn't look like a tar archive.");
309 msg("Skipping to next header");
317 /* head->header.name[NAMSIZ-1] = '\0'; */
318 /* fprintf(stderr,"file %s\n",head->header.name); */
319 if((name
=name_scan(current_file_name
))==(struct name
*)0) {
321 /* fprintf(stderr,"Skip %ld\n",(long)(hstat.st_size)); */
322 if (head
->header
.isextended
)
323 skip_extended_headers();
324 skip_file((long)(hstat
.st_size
));
336 /* fprintf(stderr,"Out of first loop\n"); */
345 if(write_archive_to_stdout
)
346 write_archive_to_stdout
= 0;
347 new_block
= (union record
*)malloc(blocksize
);
349 msg("Can't allocate secondary block of %d bytes",blocksize
);
353 /* Save away records before this one in this block */
354 number_of_new_records
=ar_record
-ar_block
;
355 number_of_records_needed
= blocking
- number_of_new_records
;
356 if(number_of_new_records
)
357 bcopy((void *)ar_block
,(void *)new_block
,(number_of_new_records
)*RECORDSIZE
);
359 /* fprintf(stderr,"Saved %d recs, need %d more\n",number_of_new_records,number_of_records_needed); */
361 if (head
->header
.isextended
)
362 skip_extended_headers();
363 skip_file((long)(hstat
.st_size
));
365 /* goto flush_file; */
368 /* Fill in a block */
370 if(ar_record
==ar_last
) {
371 /* fprintf(stderr,"New block\n"); */
373 number_of_blocks_read
++;
375 sub_status
= read_header();
376 /* fprintf(stderr,"Header type %d\n",sub_status); */
378 if(sub_status
==2 && f_ignorez
) {
382 if(sub_status
==EOF
|| sub_status
==2) {
384 bzero(new_block
[number_of_new_records
].charptr
,RECORDSIZE
*number_of_records_needed
);
385 number_of_new_records
+=number_of_records_needed
;
386 number_of_records_needed
= 0;
392 msg("Deleting non-header from archive.");
397 /* Found another header. Yipee! */
398 /* head->header.name[NAMSIZ-1] = '\0'; */
399 /* fprintf(stderr,"File %s ",head->header.name); */
400 if(name
=name_scan(current_file_name
)) {
402 /* fprintf(stderr,"Flush it\n"); */
404 /* decode_header(head,&hstat,&dummy_head,0); */
406 number_of_records_to_skip
=(hstat
.st_size
+RECORDSIZE
-1)/RECORDSIZE
;
407 /* fprintf(stderr,"Flushing %d recs from %s\n",number_of_records_to_skip,head->header.name); */
409 while(ar_last
-ar_record
<=number_of_records_to_skip
) {
411 /* fprintf(stderr,"Block: %d <= %d ",ar_last-ar_record,number_of_records_to_skip); */
412 number_of_records_to_skip
-= (ar_last
- ar_record
);
414 number_of_blocks_read
++;
415 /* fprintf(stderr,"Block %d left\n",number_of_records_to_skip); */
417 ar_record
+=number_of_records_to_skip
;
418 /* fprintf(stderr,"Final %d\n",number_of_records_to_skip); */
419 number_of_records_to_skip
= 0;
424 new_block
[number_of_new_records
]= *head
;
425 number_of_new_records
++;
426 number_of_records_needed
--;
427 number_of_records_to_keep
=(hstat
.st_size
+RECORDSIZE
-1)/RECORDSIZE
;
429 if(number_of_records_needed
==0)
432 number_of_kept_records_in_block
= ar_last
- ar_record
;
433 if(number_of_kept_records_in_block
> number_of_records_to_keep
)
434 number_of_kept_records_in_block
= number_of_records_to_keep
;
436 /* fprintf(stderr,"Need %d kept_in %d keep %d\n",blocking,number_of_kept_records_in_block,number_of_records_to_keep); */
438 while(number_of_records_to_keep
) {
441 if(ar_record
==ar_last
) {
442 /* fprintf(stderr,"Flush. . .\n"); */
444 number_of_blocks_read
++;
446 number_of_kept_records_in_block
= blocking
;
447 if(number_of_kept_records_in_block
> number_of_records_to_keep
)
448 number_of_kept_records_in_block
= number_of_records_to_keep
;
450 n
= number_of_kept_records_in_block
;
451 if(n
>number_of_records_needed
)
452 n
= number_of_records_needed
;
454 /* fprintf(stderr,"Copying %d\n",n); */
455 bcopy((void *)ar_record
, (void *)(new_block
+number_of_new_records
), n
*RECORDSIZE
);
456 number_of_new_records
+= n
;
457 number_of_records_needed
-= n
;
459 number_of_records_to_keep
-= n
;
460 number_of_kept_records_in_block
-= n
;
461 /* fprintf(stderr,"Now new %d need %d keep %d keep_in %d rec %d/%d\n",
462 number_of_new_records,number_of_records_needed,number_of_records_to_keep,
463 number_of_kept_records_in_block,ar_record-ar_block,ar_last-ar_block); */
465 if(number_of_records_needed
== 0) {
480 /* fprintf(stderr,"Write block\n"); */
481 /* We've filled out a block. Write it out. */
483 /* Backspace back to where we started. . . */
485 (void)move_arch(-(number_of_blocks_read
+1));
487 save_block
= ar_block
;
488 ar_block
= new_block
;
496 ar_block
= save_block
;
499 /* Move the tape head back to where we were */
501 (void)move_arch(number_of_blocks_read
);
502 number_of_blocks_read
--;
505 number_of_records_needed
= blocking
;
506 number_of_new_records
= 0;
509 /* Move archive descriptor by n blocks worth. If n is positive we move
510 forward, else we move negative. If its a tape, MTIOCTOP had better
511 work. If its something else, we try to seek on it. If we can't
530 if((er
=rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
532 if(errno
==EIO
&& (er
=rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
536 cur
=rmtlseek(archive
,0L,1);
539 /* fprintf(stderr,"Fore to %x\n",cur); */
540 if(rmtlseek(archive
,cur
,0)!=cur
) {
541 /* Lseek failed. Try a different method */
542 msg("Couldn't re-position archive file.");