]>
Dogcows Code - chaz/tar/blob - src/buffer.c
1 /* Buffer management for tar.
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. */
21 * Buffer management for tar.
23 * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
31 #include <sys/types.h> /* For non-Berkeley systems */
36 #ifdef HAVE_SYS_MTIO_H
37 #include <sys/ioctl.h>
54 #include <sys/inode.h>
62 /* Either stdout or stderr: The thing we write messages (standard msgs, not
63 errors) to. Stdout unless we're writing a pipe, in which case stderr */
64 FILE *msg_file
= stdout
;
66 #define STDIN 0 /* Standard input file descriptor */
67 #define STDOUT 1 /* Standard output file descriptor */
69 #define PREAD 0 /* Read file descriptor from pipe() */
70 #define PWRITE 1 /* Write file descriptor from pipe() */
72 #define MAGIC_STAT 105 /* Magic status returned by child, if
73 it can't exec. We hope compress/sh
74 never return this status! */
84 int backspace_output();
85 extern void finish_header();
93 /* Obnoxious test to see if dimwit is trying to dump the archive */
99 * The record pointed to by save_rec should not be overlaid
100 * when reading in a new tape block. Copy it to record_save_area first, and
101 * change the pointer in *save_rec to point to record_save_area.
102 * Saved_recno records the record number at the time of the save.
103 * This is used by annofile() to print the record number of a file's
106 static union record
**save_rec
;
107 union record record_save_area
;
108 static long saved_recno
;
111 * PID of child program, if f_compress or remote archive access.
113 static int childpid
= 0;
116 * Record number of the start of this block of records
121 * Error recovery stuff
123 static int r_error_count
;
126 * Have we hit EOF yet?
130 /* Checkpointing counter */
131 static int checkpoint
;
133 /* JF we're reading, but we just read the last record and its time to update */
134 extern time_to_start_writing
;
135 int file_to_switch_to
= -1; /* If remote update, close archive, and use
136 this descriptor to write to */
138 static int volno
= 1; /* JF which volume of a multi-volume tape
140 static int global_volno
= 1; /* Volume number to print in external messages. */
142 char *save_name
= 0; /* Name of the file we are currently writing */
143 long save_totsize
; /* total size of file we are writing. Only
144 valid if save_name is non_zero */
145 long save_sizeleft
; /* Where we are in the file we are writing.
146 Only valid if save_name is non-zero */
148 int write_archive_to_stdout
;
150 /* Used by fl_read and fl_write to store the real info about saved names */
151 static char real_s_name
[NAMSIZ
];
152 static long real_s_totsize
;
153 static long real_s_sizeleft
;
155 /* Reset the EOF flag (if set), and re-set ar_record, etc */
163 ar_last
=ar_block
+blocking
;
169 * Return the location of the next available input or output record.
170 * Return NULL for EOF. Once we have returned NULL, we just keep returning
171 * it, to avoid accidentally going on to the next file on the "tape".
176 if (ar_record
== ar_last
) {
178 return (union record
*)NULL
; /* EOF */
180 if (ar_record
== ar_last
) {
182 return (union record
*)NULL
; /* EOF */
190 * Indicate that we have used all records up thru the argument.
191 * (should the arg have an off-by-1? XXX FIXME)
197 while(rec
>= ar_record
)
200 * Do NOT flush the archive here. If we do, the same
201 * argument to userec() could mean the next record (if the
202 * input block is exactly one record long), which is not what
205 if (ar_record
> ar_last
)
211 * Return a pointer to the end of the current records buffer.
212 * All the space between findrec() and endofrecs() is available
213 * for filling with data, or taking data from.
223 * Duplicate a file descriptor into a certain slot.
224 * Equivalent to BSD "dup2" with error reporting.
235 if(err
<0 && errno
!=EBADF
) {
236 msg_perror("Cannot close descriptor %d",to
);
241 msg_perror("cannot dup %s",msg
);
252 fprintf(stderr
,"MS-DOS %s can't use compressed or remote archives\n",tar
);
273 msg_perror("cannot fork");
277 /* We're the parent. Clean up and be happy */
278 /* This, at least, is easy */
283 ck_close(pipe
[WRITE
]);
285 archive
= pipe
[WRITE
];
286 ck_close(pipe
[READ
]);
293 dupto(pipe
[WRITE
],STDOUT
,"(child) pipe to stdout");
294 ck_close(pipe
[READ
]);
296 dupto(pipe
[READ
],STDIN
,"(child) pipe to stdin");
297 ck_close(pipe
[WRITE
]);
300 /* We need a child tar only if
301 1: we're reading/writing stdin/out (to force reblocking)
302 2: the file is to be accessed by rmt (compress doesn't know how)
303 3: the file is not a plain file */
305 if(!(ar_files
[0][0]=='-' && ar_files
[0][1]=='\0') && isfile(ar_files
[0]))
307 if(!(ar_files
[0][0]=='-' && ar_file
[0][1]=='\0') && !_remdev(ar_files
[0]) && isfile(ar_files
[0]))
310 /* We don't need a child tar. Open the archive */
312 archive
=open(ar_files
[0], O_RDONLY
|O_BINARY
, 0666);
314 msg_perror("can't open archive %s",ar_files
[0]);
317 dupto(archive
,STDIN
,"archive to stdin");
318 /* close(archive); */
320 archive
=creat(ar_files
[0],0666);
322 msg_perror("can't open archive %s",ar_files
[0]);
325 dupto(archive
,STDOUT
,"archive to stdout");
326 /* close(archive); */
329 /* We need a child tar */
334 msg_perror("child can't fork");
339 /* About to exec compress: set up the files */
341 dupto(kidpipe
[READ
],STDIN
,"((child)) pipe to stdin");
342 ck_close(kidpipe
[WRITE
]);
343 /* dup2(pipe[WRITE],STDOUT); */
345 /* dup2(pipe[READ],STDIN); */
346 dupto(kidpipe
[WRITE
],STDOUT
,"((child)) pipe to stdout");
347 ck_close(kidpipe
[READ
]);
349 /* ck_close(pipe[READ]); */
350 /* ck_close(pipe[WRITE]); */
351 /* ck_close(kidpipe[READ]);
352 ck_close(kidpipe[WRITE]); */
354 /* Grandchild. Do the right thing, namely sit here and
355 read/write the archive, and feed stuff back to compress */
358 dupto(kidpipe
[WRITE
],STDOUT
,"[child] pipe to stdout");
359 ck_close(kidpipe
[READ
]);
361 dupto(kidpipe
[READ
],STDIN
,"[child] pipe to stdin");
362 ck_close(kidpipe
[WRITE
]);
365 if (ar_file
[0] == '-' && ar_file
[1] == '\0') {
370 } else /* This can't happen if (ar_reading==2)
371 archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666);
372 else */if(ar_reading
)
373 archive
= rmtopen(ar_files
[0], O_RDONLY
|O_BINARY
, 0666);
375 archive
= rmtcreat(ar_files
[0], 0666);
378 msg_perror("can't open archive %s",ar_files
[0]);
389 err
=rmtread(archive
, ar_block
->charptr
,(int)(blocksize
));
396 ptr
= ar_block
->charptr
;
399 count
= (max
<RECORDSIZE
) ? max
: RECORDSIZE
;
400 err
=write(STDOUT
,ptr
,count
);
403 msg_perror("can't write to compress");
406 msg("write to compress short %d bytes",count
-err
);
407 count
= (err
<0) ? 0 : err
;
419 ptr
= ar_block
->charptr
;
421 err
=read(STDIN
,ptr
,(n
<RECORDSIZE
) ? n
: RECORDSIZE
);
432 bzero(ar_block
->charptr
+blocksize
-n
,n
);
433 err
=rmtwrite(archive
,ar_block
->charptr
,blocksize
);
441 msg_perror("can't read from compress");
444 err
=rmtwrite(archive
, ar_block
->charptr
, (int)blocksize
);
450 /* close_archive(); */
454 /* So we should exec compress (-d) */
456 execlp("compress", "compress", "-d", (char *)0);
458 execlp("compress", "compress", (char *)0);
459 msg_perror("can't exec compress");
464 /* return non-zero if p is the name of a directory */
473 if(S_ISREG(stbuf
.st_mode
))
481 * Open an archive file. The argument specifies whether we are
482 * reading or writing.
484 /* JF if the arg is 2, open for reading and writing. */
486 open_archive(reading
)
489 msg_file
= f_exstdout
? stderr
: stdout
;
491 if (blocksize
== 0) {
492 msg("invalid value for blocksize");
497 msg("No archive name given, what should I do?");
503 ar_block
= (union record
*) valloc((unsigned)(blocksize
+(2*RECORDSIZE
)));
507 ar_block
= (union record
*) valloc((unsigned)blocksize
);
509 msg("could not allocate memory for blocking factor %d",
514 ar_record
= ar_block
;
515 ar_last
= ar_block
+ blocking
;
516 ar_reading
= reading
;
519 if(reading
==2 || f_verify
) {
520 msg("cannot update or verify compressed archives");
524 msg ("cannot use multi-volume compressed archives");
528 if(!reading
&& ar_files
[0][0]=='-' && ar_files
[0][1]=='\0')
530 /* child_open(rem_host, rem_file); */
531 } else if (ar_files
[0][0] == '-' && ar_files
[0][1] == '\0') {
532 f_reblock
++; /* Could be a pipe, be safe */
534 msg("can't verify stdin/stdout archive");
540 write_archive_to_stdout
++;
547 } else if (reading
==2 || f_verify
) {
548 archive
= rmtopen(ar_files
[0], O_RDWR
|O_CREAT
|O_BINARY
, 0666);
550 archive
= rmtopen(ar_files
[0], O_RDONLY
|O_BINARY
, 0666);
552 archive
= rmtcreat(ar_files
[0], 0666);
555 msg_perror("can't open %s",ar_files
[0]);
559 if(!_isrmt(archive
)) {
560 struct stat tmp_stat
;
562 fstat(archive
,&tmp_stat
);
563 if(S_ISREG(tmp_stat
.st_mode
)) {
564 ar_dev
=tmp_stat
.st_dev
;
565 ar_ino
=tmp_stat
.st_ino
;
571 setmode(archive
, O_BINARY
);
575 ar_last
= ar_block
; /* Set up for 1st block = # 0 */
576 (void) findrec(); /* Read it in, check for EOF */
584 ptr
=malloc(strlen(f_volhdr
)+20);
585 sprintf(ptr
,"%s Volume %d",f_volhdr
,1);
591 msg("Archive not labelled to match %s",f_volhdr
);
594 if (re_match (label_pattern
, head
->header
.name
,
595 strlen (head
->header
.name
), 0, 0) < 0) {
596 msg ("Volume mismatch! %s!=%s", f_volhdr
,
601 if(strcmp(ptr
,head
->header
.name
)) {
602 msg("Volume mismatch! %s!=%s",ptr
,head
->header
.name
);
609 } else if(f_volhdr
) {
610 bzero((void *)ar_block
,RECORDSIZE
);
612 sprintf(ar_block
->header
.name
,"%s Volume 1",f_volhdr
);
614 strcpy(ar_block
->header
.name
,f_volhdr
);
615 ar_block
->header
.linkflag
= LF_VOLHDR
;
616 to_oct(time(0), 1+12, ar_block
->header
.mtime
);
617 finish_header(ar_block
);
624 * Remember a union record * as pointing to something that we
625 * need to keep when reading onward in the file. Only one such
626 * thing can be remembered at once, and it only works when reading
629 * We calculate "offset" then add it because some compilers end up
630 * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
631 * subtracting ar_block from that, shifting it back, losing the top 9 bits.
635 union record
**pointer
;
640 offset
= ar_record
- ar_block
;
641 saved_recno
= baserec
+ offset
;
645 * Perform a write to flush the buffer.
648 /*send_buffer_to_file();
650 deal_with_new_volume_stuff();
651 send_buffer_to_file();
660 static long bytes_written
= 0;
662 if (f_checkpoint
&& ! (++checkpoint
% 10))
663 msg ("Write checkpoint %d\n", checkpoint
);
664 if(tape_length
&& bytes_written
>= tape_length
* 1024) {
668 err
= rmtwrite(archive
, ar_block
->charptr
,(int) blocksize
);
669 if(err
!=blocksize
&& !f_multivol
)
672 tot_written
+= blocksize
;
676 if (err
== blocksize
) {
685 if(save_name
[1]==':')
688 while(*save_name
=='/')
691 strcpy(real_s_name
,save_name
);
692 real_s_totsize
= save_totsize
;
693 real_s_sizeleft
= save_sizeleft
;
698 /* We're multivol Panic if we didn't get the right kind of response */
699 /* ENXIO is for the UNIX PC */
700 if(err
<0 && errno
!=ENOSPC
&& errno
!=EIO
&& errno
!=ENXIO
)
703 /* If error indicates a short write, we just move to the next tape. */
708 if(f_volhdr
&& real_s_name
[0]) {
711 } else if(f_volhdr
|| real_s_name
[0]) {
717 bzero((void *)ar_block
,RECORDSIZE
);
718 sprintf(ar_block
->header
.name
,"%s Volume %d",f_volhdr
,volno
);
719 to_oct(time(0), 1+12, ar_block
->header
.mtime
);
720 ar_block
->header
.linkflag
= LF_VOLHDR
;
721 finish_header(ar_block
);
728 bzero((void *)ar_block
,RECORDSIZE
);
729 strcpy(ar_block
->header
.name
,real_s_name
);
730 ar_block
->header
.linkflag
= LF_MULTIVOL
;
731 to_oct((long)real_s_sizeleft
,1+12,
732 ar_block
->header
.size
);
733 to_oct((long)real_s_totsize
-real_s_sizeleft
,
734 1+12,ar_block
->header
.offset
);
737 finish_header(ar_block
);
743 err
= rmtwrite(archive
, ar_block
->charptr
,(int) blocksize
);
747 tot_written
+= blocksize
;
750 bytes_written
= blocksize
;
753 bcopy((void *)(ar_block
+blocking
-copy_back
),
755 copy_back
*RECORDSIZE
);
756 ar_record
+=copy_back
;
758 if(real_s_sizeleft
>=copy_back
*RECORDSIZE
)
759 real_s_sizeleft
-=copy_back
*RECORDSIZE
;
760 else if((real_s_sizeleft
+RECORDSIZE
-1)/RECORDSIZE
<=copy_back
)
761 real_s_name
[0] = '\0';
764 if(save_name
[1]==':')
767 while(*save_name
=='/')
770 strcpy(real_s_name
,save_name
);
771 real_s_sizeleft
= save_sizeleft
;
772 real_s_totsize
=save_totsize
;
778 /* Handle write errors on the archive. Write errors are always fatal */
779 /* Hitting the end of a volume does not cause a write error unless the write
780 * was the first block of the volume */
787 msg_perror("can't write to %s",ar_files
[cur_ar_file
]);
790 msg("only wrote %u of %u bytes to %s",err
,blocksize
,ar_files
[cur_ar_file
]);
796 * Handle read errors on the archive.
798 * If the read should be retried, readerror() returns to the caller.
803 # define READ_ERROR_MAX 10
805 read_error_flag
++; /* Tell callers */
807 msg_perror("read error on %s",ar_files
[cur_ar_file
]);
810 /* First block of tape. Probably stupidity error */
815 * Read error in mid archive. We retry up to READ_ERROR_MAX times
816 * and then give up on reading the archive. We set read_error_flag
817 * for our callers, so they can cope if they want.
819 if (r_error_count
++ > READ_ERROR_MAX
) {
820 msg("Too many errors, quitting.");
828 * Perform a read to flush the buffer.
833 int err
; /* Result from system call */
834 int left
; /* Bytes left */
835 char *more
; /* Pointer to next byte to read */
837 if (f_checkpoint
&& ! (++checkpoint
% 10))
838 msg ("Read checkpoint %d\n", checkpoint
);
841 * Clear the count of errors. This only applies to a single
842 * call to fl_read. We leave read_error_flag alone; it is
843 * only turned off by higher level software.
845 r_error_count
= 0; /* Clear error count */
848 * If we are about to wipe out a record that
849 * somebody needs to keep, copy it out to a holding
850 * area and adjust somebody's pointer to it.
853 *save_rec
>= ar_record
&&
854 *save_rec
< ar_last
) {
855 record_save_area
= **save_rec
;
856 *save_rec
= &record_save_area
;
858 if(write_archive_to_stdout
&& baserec
!=0) {
859 err
=rmtwrite(1, ar_block
->charptr
, blocksize
);
865 if(save_name
!=real_s_name
) {
867 if(save_name
[1]==':')
870 while(*save_name
=='/')
873 strcpy(real_s_name
,save_name
);
874 save_name
=real_s_name
;
876 real_s_totsize
= save_totsize
;
877 real_s_sizeleft
= save_sizeleft
;
887 err
= rmtread(archive
, ar_block
->charptr
, (int)blocksize
);
888 if (err
== blocksize
)
891 if((err
== 0 || (err
<0 && errno
==ENOSPC
) || (err
> 0 && !f_reblock
)) && f_multivol
) {
895 if(new_volume((cmd_mode
==CMD_APPEND
|| cmd_mode
==CMD_CAT
|| cmd_mode
==CMD_UPDATE
) ? 2 : 1)<0)
898 err
= rmtread(archive
, ar_block
->charptr
,(int) blocksize
);
908 if(head
->header
.linkflag
==LF_VOLHDR
) {
913 ptr
=(char *)malloc(strlen(f_volhdr
)+20);
914 sprintf(ptr
,"%s Volume %d",f_volhdr
,volno
);
916 if (re_match (label_pattern
, head
->header
.name
,
917 strlen (head
->header
.name
),
919 msg("Volume mismatch! %s!=%s",f_volhdr
,
927 if(strcmp(ptr
,head
->header
.name
)) {
928 msg("Volume mismatch! %s!=%s",ptr
,head
->header
.name
);
938 fprintf(msg_file
,"Reading %s\n",head
->header
.name
);
940 } else if(f_volhdr
) {
941 msg("Warning: No volume header!");
947 if(head
->header
.linkflag
!=LF_MULTIVOL
|| strcmp(head
->header
.name
,real_s_name
)) {
948 msg("%s is not continued on this volume!",real_s_name
);
953 if(real_s_totsize
!=from_oct(1+12,head
->header
.size
)+from_oct(1+12,head
->header
.offset
)) {
954 msg("%s is the wrong size (%ld!=%ld+%ld)",
955 head
->header
.name
,save_totsize
,
956 from_oct(1+12,head
->header
.size
),
957 from_oct(1+12,head
->header
.offset
));
962 if(real_s_totsize
-real_s_sizeleft
!=from_oct(1+12,head
->header
.offset
)) {
963 msg("This volume is out of sequence");
972 } else if (err
< 0) {
974 goto error_loop
; /* Try again */
978 more
= ar_block
->charptr
+ err
;
979 left
= blocksize
- err
;
982 if (0 == (((unsigned)left
) % RECORDSIZE
)) {
983 /* FIXME, for size=0, multi vol support */
984 /* On the first block, warn about the problem */
985 if (!f_reblock
&& baserec
== 0 && f_verbose
&& err
> 0) {
986 /* msg("Blocksize = %d record%s",
987 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
988 msg("Blocksize = %d records", err
/ RECORDSIZE
);
990 ar_last
= ar_block
+ ((unsigned)(blocksize
- left
))/RECORDSIZE
;
995 * User warned us about this. Fix up.
999 err
= rmtread(archive
, more
, (int)left
);
1002 goto error2loop
; /* Try again */
1005 msg("archive %s EOF not on block boundary",ar_files
[cur_ar_file
]);
1013 msg("only read %d bytes from archive %s",err
,ar_files
[cur_ar_file
]);
1020 * Flush the current buffer to/from the archive.
1027 baserec
+= ar_last
- ar_block
; /* Keep track of block #s */
1028 ar_record
= ar_block
; /* Restore pointer to start */
1029 ar_last
= ar_block
+ blocking
; /* Restore pointer to end */
1032 if(time_to_start_writing
) {
1033 time_to_start_writing
=0;
1036 if(file_to_switch_to
>=0) {
1037 if((c
=rmtclose(archive
))<0)
1038 msg_perror("Warning: can't close %s(%d,%d)",ar_files
[cur_ar_file
],archive
,c
);
1040 archive
=file_to_switch_to
;
1042 (void)backspace_output();
1051 /* Backspace the archive descriptor by one blocks worth.
1052 If its a tape, MTIOCTOP will work. If its something else,
1053 we try to seek on it. If we can't seek, we lose! */
1059 extern char *output_start
;
1066 if((rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1068 if(errno
==EIO
&& (rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1072 cur
=rmtlseek(archive
,0L,1);
1074 /* Seek back to the beginning of this block and
1075 start writing there. */
1077 if(rmtlseek(archive
,cur
,0)!=cur
) {
1078 /* Lseek failed. Try a different method */
1079 msg("Couldn't backspace archive file. It may be unreadable without -i.");
1080 /* Replace the first part of the block with nulls */
1081 if(ar_block
->charptr
!=output_start
)
1082 bzero(ar_block
->charptr
,output_start
-ar_block
->charptr
);
1090 * Close the archive file.
1099 if (time_to_start_writing
|| !ar_reading
)
1101 if(cmd_mode
==CMD_DELETE
) {
1104 pos
= rmtlseek(archive
,0L,1);
1106 (void) ftruncate(archive
,pos
);
1108 (void)rmtwrite(archive
,"",0);
1114 if((c
=rmtclose(archive
))<0)
1115 msg_perror("Warning: can't close %s(%d,%d)",ar_files
[cur_ar_file
],archive
,c
);
1120 * Loop waiting for the right child to die, or for
1123 while (((child
= wait(&status
)) != childpid
) && child
!= -1)
1127 switch (WTERMSIG(status
)) {
1129 /* Child voluntarily terminated -- but why? */
1130 if (WEXITSTATUS(status
) == MAGIC_STAT
) {
1131 exit(EX_SYSTEM
);/* Child had trouble */
1133 if (WEXITSTATUS(status
) == (SIGPIPE
+ 128)) {
1135 * /bin/sh returns this if its child
1136 * dies with SIGPIPE. 'Sok.
1139 } else if (WEXITSTATUS(status
))
1140 msg("child returned status %d",
1141 WEXITSTATUS(status
));
1143 break; /* This is OK. */
1146 msg("child died with signal %d%s",
1148 WIFCOREDUMPED(status
)? " (core dumped)": "");
1152 #endif /* __MSDOS__ */
1158 * Message management.
1160 * anno writes a message prefix on stream (eg stdout, stderr).
1162 * The specified prefix is normally output followed by a colon and a space.
1163 * However, if other command line options are set, more output can come
1164 * out, such as the record # within the archive.
1166 * If the specified prefix is NULL, no output is produced unless the
1167 * command line option(s) are set.
1169 * If the third argument is 1, the "saved" record # is used; if 0, the
1170 * "current" record # is used.
1173 anno(stream
, prefix
, savedp
)
1179 char buffer
[MAXANNO
]; /* Holds annorecment */
1180 # define ANNOWIDTH 13
1186 /* Make sure previous output gets out in sequence */
1187 if (stream
== stderr
)
1191 fputs(prefix
, stream
);
1194 offset
= ar_record
- ar_block
;
1195 (void) sprintf(buffer
, "rec %d: ",
1196 savedp
? saved_recno
:
1198 fputs(buffer
, stream
);
1199 space
= ANNOWIDTH
- strlen(buffer
);
1201 fprintf(stream
, "%*s", space
, "");
1203 } else if (prefix
) {
1204 fputs(prefix
, stream
);
1205 fputs(": ", stream
);
1211 /* Called to initialize the global volume number. */
1213 init_volume_number ()
1217 vf
= fopen (f_volno_file
, "r");
1218 if (!vf
&& errno
!= ENOENT
)
1219 msg_perror ("%s", f_volno_file
);
1223 fscanf (vf
, "%d", &global_volno
);
1228 /* Called to write out the closing global volume number. */
1230 closeout_volume_number ()
1234 vf
= fopen (f_volno_file
, "w");
1236 msg_perror ("%s", f_volno_file
);
1239 fprintf (vf
, "%d\n", global_volno
);
1244 /* We've hit the end of the old volume. Close it and open the next one */
1245 /* Values for type: 0: writing 1: reading 2: updating */
1253 static FILE *read_file
= 0;
1254 extern int now_verifying
;
1255 extern char TTY_NAME
[];
1257 static int looped
= 0;
1259 if(!read_file
&& !f_run_script_at_end
)
1260 read_file
= (archive
==0) ? fopen(TTY_NAME
, "r") : stdin
;
1266 if((c
=rmtclose(archive
))<0)
1267 msg_perror("Warning: can't close %s(%d,%d)",ar_files
[cur_ar_file
],archive
,c
);
1272 if (cur_ar_file
== n_ar_files
)
1281 /* We have to prompt from now on. */
1282 if (f_run_script_at_end
)
1283 system(info_script
);
1285 fprintf(msg_file
,"\007Prepare volume #%d for %s and hit return: ",global_volno
, ar_files
[cur_ar_file
]);
1287 if(fgets(inbuf
,sizeof(inbuf
),read_file
)==0) {
1288 fprintf(msg_file
,"EOF? What does that mean?");
1289 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1290 msg("Warning: Archive is INCOMPLETE!");
1293 if(inbuf
[0]=='\n' || inbuf
[0]=='y' || inbuf
[0]=='Y')
1300 n [name] Give a new filename for the next (and subsequent) volume(s)\n\
1302 ! Spawn a subshell\n\
1303 ? Print this list\n");
1307 case 'q': /* Quit */
1308 fprintf(msg_file
,"No new volume; exiting.\n");
1309 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1310 msg("Warning: Archive is INCOMPLETE!");
1313 case 'n': /* Get new file name */
1316 static char *old_name
;
1318 for(q
= &inbuf
[1];*q
==' ' || *q
=='\t';q
++)
1323 old_name
=p
=(char *)malloc((unsigned)(strlen(q
)+2));
1325 msg("Can't allocate memory for name");
1329 ar_files
[cur_ar_file
]=p
;
1335 spawnl(P_WAIT
,getenv("COMSPEC"),"-",0);
1337 /* JF this needs work! */
1340 msg_perror("can't fork!");
1344 if(p
==0) p
="/bin/sh";
1345 execlp(p
,"-sh","-i",0);
1346 msg_perror("can't exec a shell %s",p
);
1359 if(type
==2 || f_verify
)
1360 archive
=rmtopen(ar_files
[cur_ar_file
],O_RDWR
|O_CREAT
,0666);
1362 archive
=rmtopen(ar_files
[cur_ar_file
],O_RDONLY
,0666);
1364 archive
=rmtcreat(ar_file
[cur_ar_file
],0666);
1369 msg_perror("can't open %s",ar_files
[cur_ar_file
]);
1373 setmode(archive
,O_BINARY
);
1378 /* this is a useless function that takes a buffer returned by wantbytes
1379 and does nothing with it. If the function called by wantbytes returns
1380 an error indicator (non-zero), this function is called for the rest of
1391 /* Some other routine wants SIZE bytes in the archive. For each chunk of
1392 the archive, call FUNC with the size of the chunk, and the address of
1393 the chunk it can work with.
1396 wantbytes(size
,func
)
1404 data
= findrec()->charptr
;
1405 if (data
== NULL
) { /* Check it... */
1406 msg("Unexpected EOF on archive file");
1409 data_size
= endofrecs()->charptr
- data
;
1412 if((*func
)(data_size
,data
))
1414 userec((union record
*)(data
+ data_size
- 1));
This page took 0.100965 seconds and 5 git commands to generate.