]>
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
);
272 msg_perror("cannot fork");
276 /* We're the parent. Clean up and be happy */
277 /* This, at least, is easy */
282 ck_close(pipe
[WRITE
]);
284 archive
= pipe
[WRITE
];
285 ck_close(pipe
[READ
]);
292 dupto(pipe
[WRITE
],STDOUT
,"(child) pipe to stdout");
293 ck_close(pipe
[READ
]);
295 dupto(pipe
[READ
],STDIN
,"(child) pipe to stdin");
296 ck_close(pipe
[WRITE
]);
299 /* We need a child tar only if
300 1: we're reading/writing stdin/out (to force reblocking)
301 2: the file is to be accessed by rmt (compress doesn't know how)
302 3: the file is not a plain file */
304 if(!(ar_file
[0]=='-' && ar_file
[1]=='\0') && isfile(ar_file
))
306 if(!(ar_file
[0]=='-' && ar_file
[1]=='\0') && !_remdev(ar_file
) && isfile(ar_file
))
309 /* We don't need a child tar. Open the archive */
311 archive
=open(ar_file
, O_RDONLY
|O_BINARY
, 0666);
313 msg_perror("can't open archive %s",ar_file
);
316 dupto(archive
,STDIN
,"archive to stdin");
317 /* close(archive); */
319 archive
=creat(ar_file
,0666);
321 msg_perror("can't open archive %s",ar_file
);
324 dupto(archive
,STDOUT
,"archive to stdout");
325 /* close(archive); */
328 /* We need a child tar */
333 msg_perror("child can't fork");
338 /* About to exec compress: set up the files */
340 dupto(kidpipe
[READ
],STDIN
,"((child)) pipe to stdin");
341 ck_close(kidpipe
[WRITE
]);
342 /* dup2(pipe[WRITE],STDOUT); */
344 /* dup2(pipe[READ],STDIN); */
345 dupto(kidpipe
[WRITE
],STDOUT
,"((child)) pipe to stdout");
346 ck_close(kidpipe
[READ
]);
348 /* ck_close(pipe[READ]); */
349 /* ck_close(pipe[WRITE]); */
350 /* ck_close(kidpipe[READ]);
351 ck_close(kidpipe[WRITE]); */
353 /* Grandchild. Do the right thing, namely sit here and
354 read/write the archive, and feed stuff back to compress */
357 dupto(kidpipe
[WRITE
],STDOUT
,"[child] pipe to stdout");
358 ck_close(kidpipe
[READ
]);
360 dupto(kidpipe
[READ
],STDIN
,"[child] pipe to stdin");
361 ck_close(kidpipe
[WRITE
]);
364 if (ar_file
[0] == '-' && ar_file
[1] == '\0') {
369 } else /* This can't happen if (ar_reading==2)
370 archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
371 else */if(ar_reading
)
372 archive
= rmtopen(ar_file
, O_RDONLY
|O_BINARY
, 0666);
374 archive
= rmtcreat(ar_file
, 0666);
377 msg_perror("can't open archive %s",ar_file
);
388 err
=rmtread(archive
, ar_block
->charptr
,(int)(blocksize
));
395 ptr
= ar_block
->charptr
;
398 count
= (max
<RECORDSIZE
) ? max
: RECORDSIZE
;
399 err
=write(STDOUT
,ptr
,count
);
402 msg_perror("can't write to compress");
405 msg("write to compress short %d bytes",count
-err
);
406 count
= (err
<0) ? 0 : err
;
418 ptr
= ar_block
->charptr
;
420 err
=read(STDIN
,ptr
,(n
<RECORDSIZE
) ? n
: RECORDSIZE
);
431 bzero(ar_block
->charptr
+blocksize
-n
,n
);
432 err
=rmtwrite(archive
,ar_block
->charptr
,blocksize
);
440 msg_perror("can't read from compress");
443 err
=rmtwrite(archive
, ar_block
->charptr
, (int)blocksize
);
449 /* close_archive(); */
453 /* So we should exec compress (-d) */
455 execlp("compress", "compress", "-d", (char *)0);
457 execlp("compress", "compress", (char *)0);
458 msg_perror("can't exec compress");
463 /* return non-zero if p is the name of a directory */
472 if(S_ISREG(stbuf
.st_mode
))
480 * Open an archive file. The argument specifies whether we are
481 * reading or writing.
483 /* JF if the arg is 2, open for reading and writing. */
485 open_archive(reading
)
488 msg_file
= f_exstdout
? stderr
: stdout
;
490 if (blocksize
== 0) {
491 msg("invalid value for blocksize");
496 msg("No archive name given, what should I do?");
502 ar_block
= (union record
*) valloc((unsigned)(blocksize
+(2*RECORDSIZE
)));
506 ar_block
= (union record
*) valloc((unsigned)blocksize
);
508 msg("could not allocate memory for blocking factor %d",
513 ar_record
= ar_block
;
514 ar_last
= ar_block
+ blocking
;
515 ar_reading
= reading
;
518 if(reading
==2 || f_verify
) {
519 msg("cannot update or verify compressed archives");
523 if(!reading
&& ar_file
[0]=='-' && ar_file
[1]=='\0')
525 /* child_open(rem_host, rem_file); */
526 } else if (ar_file
[0] == '-' && ar_file
[1] == '\0') {
527 f_reblock
++; /* Could be a pipe, be safe */
529 msg("can't verify stdin/stdout archive");
535 write_archive_to_stdout
++;
542 } else if (reading
==2 || f_verify
) {
543 archive
= rmtopen(ar_file
, O_RDWR
|O_CREAT
|O_BINARY
, 0666);
545 archive
= rmtopen(ar_file
, O_RDONLY
|O_BINARY
, 0666);
547 archive
= rmtcreat(ar_file
, 0666);
550 msg_perror("can't open %s",ar_file
);
554 if(!_isrmt(archive
)) {
555 struct stat tmp_stat
;
557 fstat(archive
,&tmp_stat
);
558 if(S_ISREG(tmp_stat
.st_mode
)) {
559 ar_dev
=tmp_stat
.st_dev
;
560 ar_ino
=tmp_stat
.st_ino
;
566 setmode(archive
, O_BINARY
);
570 ar_last
= ar_block
; /* Set up for 1st block = # 0 */
571 (void) findrec(); /* Read it in, check for EOF */
579 ptr
=malloc(strlen(f_volhdr
)+20);
580 sprintf(ptr
,"%s Volume %d",f_volhdr
,1);
586 msg("Archive not labelled to match %s",f_volhdr
);
589 if (re_match (label_pattern
, head
->header
.name
,
590 strlen (head
->header
.name
), 0, 0) < 0) {
591 msg ("Volume mismatch! %s!=%s", f_volhdr
,
596 if(strcmp(ptr
,head
->header
.name
)) {
597 msg("Volume mismatch! %s!=%s",ptr
,head
->header
.name
);
604 } else if(f_volhdr
) {
605 bzero((void *)ar_block
,RECORDSIZE
);
607 sprintf(ar_block
->header
.name
,"%s Volume 1",f_volhdr
);
609 strcpy(ar_block
->header
.name
,f_volhdr
);
610 ar_block
->header
.linkflag
= LF_VOLHDR
;
611 to_oct(time(0), 1+12, ar_block
->header
.mtime
);
612 finish_header(ar_block
);
619 * Remember a union record * as pointing to something that we
620 * need to keep when reading onward in the file. Only one such
621 * thing can be remembered at once, and it only works when reading
624 * We calculate "offset" then add it because some compilers end up
625 * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
626 * subtracting ar_block from that, shifting it back, losing the top 9 bits.
630 union record
**pointer
;
635 offset
= ar_record
- ar_block
;
636 saved_recno
= baserec
+ offset
;
640 * Perform a write to flush the buffer.
643 /*send_buffer_to_file();
645 deal_with_new_volume_stuff();
646 send_buffer_to_file();
655 static long bytes_written
= 0;
657 if (f_checkpoint
&& ! (++checkpoint
% 10))
658 msg ("Write checkpoint %d\n", checkpoint
);
659 if(tape_length
&& bytes_written
>= tape_length
* 1024) {
663 err
= rmtwrite(archive
, ar_block
->charptr
,(int) blocksize
);
664 if(err
!=blocksize
&& !f_multivol
)
667 tot_written
+= blocksize
;
671 if (err
== blocksize
) {
680 if(save_name
[1]==':')
683 while(*save_name
=='/')
686 strcpy(real_s_name
,save_name
);
687 real_s_totsize
= save_totsize
;
688 real_s_sizeleft
= save_sizeleft
;
693 /* We're multivol Panic if we didn't get the right kind of response */
694 /* ENXIO is for the UNIX PC */
695 if(err
<0 && errno
!=ENOSPC
&& errno
!=EIO
&& errno
!=ENXIO
)
698 /* If error indicates a short write, we just move to the next tape. */
703 if(f_volhdr
&& real_s_name
[0]) {
706 } else if(f_volhdr
|| real_s_name
[0]) {
712 bzero((void *)ar_block
,RECORDSIZE
);
713 sprintf(ar_block
->header
.name
,"%s Volume %d",f_volhdr
,volno
);
714 to_oct(time(0), 1+12, ar_block
->header
.mtime
);
715 ar_block
->header
.linkflag
= LF_VOLHDR
;
716 finish_header(ar_block
);
723 bzero((void *)ar_block
,RECORDSIZE
);
724 strcpy(ar_block
->header
.name
,real_s_name
);
725 ar_block
->header
.linkflag
= LF_MULTIVOL
;
726 to_oct((long)real_s_sizeleft
,1+12,
727 ar_block
->header
.size
);
728 to_oct((long)real_s_totsize
-real_s_sizeleft
,
729 1+12,ar_block
->header
.offset
);
732 finish_header(ar_block
);
738 err
= rmtwrite(archive
, ar_block
->charptr
,(int) blocksize
);
742 tot_written
+= blocksize
;
745 bytes_written
= blocksize
;
748 bcopy((void *)(ar_block
+blocking
-copy_back
),
750 copy_back
*RECORDSIZE
);
751 ar_record
+=copy_back
;
753 if(real_s_sizeleft
>=copy_back
*RECORDSIZE
)
754 real_s_sizeleft
-=copy_back
*RECORDSIZE
;
755 else if((real_s_sizeleft
+RECORDSIZE
-1)/RECORDSIZE
<=copy_back
)
756 real_s_name
[0] = '\0';
759 if(save_name
[1]==':')
762 while(*save_name
=='/')
765 strcpy(real_s_name
,save_name
);
766 real_s_sizeleft
= save_sizeleft
;
767 real_s_totsize
=save_totsize
;
773 /* Handle write errors on the archive. Write errors are always fatal */
774 /* Hitting the end of a volume does not cause a write error unless the write
775 * was the first block of the volume */
782 msg_perror("can't write to %s",ar_file
);
785 msg("only wrote %u of %u bytes to %s",err
,blocksize
,ar_file
);
791 * Handle read errors on the archive.
793 * If the read should be retried, readerror() returns to the caller.
798 # define READ_ERROR_MAX 10
800 read_error_flag
++; /* Tell callers */
802 msg_perror("read error on %s",ar_file
);
805 /* First block of tape. Probably stupidity error */
810 * Read error in mid archive. We retry up to READ_ERROR_MAX times
811 * and then give up on reading the archive. We set read_error_flag
812 * for our callers, so they can cope if they want.
814 if (r_error_count
++ > READ_ERROR_MAX
) {
815 msg("Too many errors, quitting.");
823 * Perform a read to flush the buffer.
828 int err
; /* Result from system call */
829 int left
; /* Bytes left */
830 char *more
; /* Pointer to next byte to read */
832 if (f_checkpoint
&& ! (++checkpoint
% 10))
833 msg ("Read checkpoint %d\n", checkpoint
);
836 * Clear the count of errors. This only applies to a single
837 * call to fl_read. We leave read_error_flag alone; it is
838 * only turned off by higher level software.
840 r_error_count
= 0; /* Clear error count */
843 * If we are about to wipe out a record that
844 * somebody needs to keep, copy it out to a holding
845 * area and adjust somebody's pointer to it.
848 *save_rec
>= ar_record
&&
849 *save_rec
< ar_last
) {
850 record_save_area
= **save_rec
;
851 *save_rec
= &record_save_area
;
853 if(write_archive_to_stdout
&& baserec
!=0) {
854 err
=rmtwrite(1, ar_block
->charptr
, blocksize
);
860 if(save_name
!=real_s_name
) {
862 if(save_name
[1]==':')
865 while(*save_name
=='/')
868 strcpy(real_s_name
,save_name
);
869 save_name
=real_s_name
;
871 real_s_totsize
= save_totsize
;
872 real_s_sizeleft
= save_sizeleft
;
882 err
= rmtread(archive
, ar_block
->charptr
, (int)blocksize
);
883 if (err
== blocksize
)
886 if((err
== 0 || (err
<0 && errno
==ENOSPC
) || (err
> 0 && !f_reblock
)) && f_multivol
) {
890 if(new_volume((cmd_mode
==CMD_APPEND
|| cmd_mode
==CMD_CAT
|| cmd_mode
==CMD_UPDATE
) ? 2 : 1)<0)
893 err
= rmtread(archive
, ar_block
->charptr
,(int) blocksize
);
903 if(head
->header
.linkflag
==LF_VOLHDR
) {
908 ptr
=(char *)malloc(strlen(f_volhdr
)+20);
909 sprintf(ptr
,"%s Volume %d",f_volhdr
,volno
);
911 if (re_match (label_pattern
, head
->header
.name
,
912 strlen (head
->header
.name
),
914 msg("Volume mismatch! %s!=%s",f_volhdr
,
922 if(strcmp(ptr
,head
->header
.name
)) {
923 msg("Volume mismatch! %s!=%s",ptr
,head
->header
.name
);
933 fprintf(msg_file
,"Reading %s\n",head
->header
.name
);
935 } else if(f_volhdr
) {
936 msg("Warning: No volume header!");
942 if(head
->header
.linkflag
!=LF_MULTIVOL
|| strcmp(head
->header
.name
,real_s_name
)) {
943 msg("%s is not continued on this volume!",real_s_name
);
948 if(real_s_totsize
!=from_oct(1+12,head
->header
.size
)+from_oct(1+12,head
->header
.offset
)) {
949 msg("%s is the wrong size (%ld!=%ld+%ld)",
950 head
->header
.name
,save_totsize
,
951 from_oct(1+12,head
->header
.size
),
952 from_oct(1+12,head
->header
.offset
));
957 if(real_s_totsize
-real_s_sizeleft
!=from_oct(1+12,head
->header
.offset
)) {
958 msg("This volume is out of sequence");
967 } else if (err
< 0) {
969 goto error_loop
; /* Try again */
973 more
= ar_block
->charptr
+ err
;
974 left
= blocksize
- err
;
977 if (0 == (((unsigned)left
) % RECORDSIZE
)) {
978 /* FIXME, for size=0, multi vol support */
979 /* On the first block, warn about the problem */
980 if (!f_reblock
&& baserec
== 0 && f_verbose
&& err
> 0) {
981 /* msg("Blocksize = %d record%s",
982 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
983 msg("Blocksize = %d records", err
/ RECORDSIZE
);
985 ar_last
= ar_block
+ ((unsigned)(blocksize
- left
))/RECORDSIZE
;
990 * User warned us about this. Fix up.
994 err
= rmtread(archive
, more
, (int)left
);
997 goto error2loop
; /* Try again */
1000 msg("archive %s EOF not on block boundary",ar_file
);
1008 msg("only read %d bytes from archive %s",err
,ar_file
);
1015 * Flush the current buffer to/from the archive.
1022 baserec
+= ar_last
- ar_block
; /* Keep track of block #s */
1023 ar_record
= ar_block
; /* Restore pointer to start */
1024 ar_last
= ar_block
+ blocking
; /* Restore pointer to end */
1027 if(time_to_start_writing
) {
1028 time_to_start_writing
=0;
1031 if(file_to_switch_to
>=0) {
1032 if((c
=rmtclose(archive
))<0)
1033 msg_perror("Warning: can't close %s(%d,%d)",ar_file
,archive
,c
);
1035 archive
=file_to_switch_to
;
1037 (void)backspace_output();
1046 /* Backspace the archive descriptor by one blocks worth.
1047 If its a tape, MTIOCTOP will work. If its something else,
1048 we try to seek on it. If we can't seek, we lose! */
1054 extern char *output_start
;
1061 if((rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1063 if(errno
==EIO
&& (rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1067 cur
=rmtlseek(archive
,0L,1);
1069 /* Seek back to the beginning of this block and
1070 start writing there. */
1072 if(rmtlseek(archive
,cur
,0)!=cur
) {
1073 /* Lseek failed. Try a different method */
1074 msg("Couldn't backspace archive file. It may be unreadable without -i.");
1075 /* Replace the first part of the block with nulls */
1076 if(ar_block
->charptr
!=output_start
)
1077 bzero(ar_block
->charptr
,output_start
-ar_block
->charptr
);
1085 * Close the archive file.
1094 if (time_to_start_writing
|| !ar_reading
)
1096 if(cmd_mode
==CMD_DELETE
) {
1099 pos
= rmtlseek(archive
,0L,1);
1101 (void) ftruncate(archive
,pos
);
1103 (void)rmtwrite(archive
,"",0);
1109 if((c
=rmtclose(archive
))<0)
1110 msg_perror("Warning: can't close %s(%d,%d)",ar_file
,archive
,c
);
1115 * Loop waiting for the right child to die, or for
1118 while (((child
= wait(&status
)) != childpid
) && child
!= -1)
1122 switch (WTERMSIG(status
)) {
1124 /* Child voluntarily terminated -- but why? */
1125 if (WEXITSTATUS(status
) == MAGIC_STAT
) {
1126 exit(EX_SYSTEM
);/* Child had trouble */
1128 if (WEXITSTATUS(status
) == (SIGPIPE
+ 128)) {
1130 * /bin/sh returns this if its child
1131 * dies with SIGPIPE. 'Sok.
1134 } else if (WEXITSTATUS(status
))
1135 msg("child returned status %d",
1136 WEXITSTATUS(status
));
1138 break; /* This is OK. */
1141 msg("child died with signal %d%s",
1143 WIFCOREDUMPED(status
)? " (core dumped)": "");
1147 #endif /* __MSDOS__ */
1153 * Message management.
1155 * anno writes a message prefix on stream (eg stdout, stderr).
1157 * The specified prefix is normally output followed by a colon and a space.
1158 * However, if other command line options are set, more output can come
1159 * out, such as the record # within the archive.
1161 * If the specified prefix is NULL, no output is produced unless the
1162 * command line option(s) are set.
1164 * If the third argument is 1, the "saved" record # is used; if 0, the
1165 * "current" record # is used.
1168 anno(stream
, prefix
, savedp
)
1174 char buffer
[MAXANNO
]; /* Holds annorecment */
1175 # define ANNOWIDTH 13
1181 /* Make sure previous output gets out in sequence */
1182 if (stream
== stderr
)
1186 fputs(prefix
, stream
);
1189 offset
= ar_record
- ar_block
;
1190 (void) sprintf(buffer
, "rec %d: ",
1191 savedp
? saved_recno
:
1193 fputs(buffer
, stream
);
1194 space
= ANNOWIDTH
- strlen(buffer
);
1196 fprintf(stream
, "%*s", space
, "");
1198 } else if (prefix
) {
1199 fputs(prefix
, stream
);
1200 fputs(": ", stream
);
1206 /* Called to initialize the global volume number. */
1208 init_volume_number ()
1212 vf
= fopen (f_volno_file
, "r");
1213 if (!vf
&& errno
!= ENOENT
)
1214 msg_perror ("%s", f_volno_file
);
1218 fscanf (vf
, "%d", &global_volno
);
1223 /* Called to write out the closing global volume number. */
1225 closeout_volume_number ()
1229 vf
= fopen (f_volno_file
, "w");
1231 msg_perror ("%s", f_volno_file
);
1234 fprintf (vf
, "%d\n", global_volno
);
1239 /* We've hit the end of the old volume. Close it and open the next one */
1240 /* Values for type: 0: writing 1: reading 2: updating */
1248 static FILE *read_file
= 0;
1249 extern int now_verifying
;
1250 extern char TTY_NAME
[];
1253 if(!read_file
&& !f_run_script_at_end
)
1254 read_file
= (archive
==0) ? fopen(TTY_NAME
, "r") : stdin
;
1260 if((c
=rmtclose(archive
))<0)
1261 msg_perror("Warning: can't close %s(%d,%d)",ar_file
,archive
,c
);
1266 if (f_run_script_at_end
)
1267 system(info_script
);
1269 fprintf(msg_file
,"\007Prepare volume #%d and hit return: ",global_volno
);
1271 if(fgets(inbuf
,sizeof(inbuf
),read_file
)==0) {
1272 fprintf(msg_file
,"EOF? What does that mean?");
1273 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1274 msg("Warning: Archive is INCOMPLETE!");
1277 if(inbuf
[0]=='\n' || inbuf
[0]=='y' || inbuf
[0]=='Y')
1284 n [name] Give a new filename for the next (and subsequent) volume(s)\n\
1286 ! Spawn a subshell\n\
1287 ? Print this list\n");
1291 case 'q': /* Quit */
1292 fprintf(msg_file
,"No new volume; exiting.\n");
1293 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1294 msg("Warning: Archive is INCOMPLETE!");
1297 case 'n': /* Get new file name */
1300 static char *old_name
;
1302 for(q
= &inbuf
[1];*q
==' ' || *q
=='\t';q
++)
1309 old_name
=p
=(char *)malloc((unsigned)(strlen(q
)+2));
1311 msg("Can't allocate memory for name");
1321 spawnl(P_WAIT
,getenv("COMSPEC"),"-",0);
1323 /* JF this needs work! */
1326 msg_perror("can't fork!");
1330 if(p
==0) p
="/bin/sh";
1331 execlp(p
,"-sh","-i",0);
1332 msg_perror("can't exec a shell %s",p
);
1343 if(type
==2 || f_verify
)
1344 archive
=rmtopen(ar_file
,O_RDWR
|O_CREAT
,0666);
1346 archive
=rmtopen(ar_file
,O_RDONLY
,0666);
1348 archive
=rmtcreat(ar_file
,0666);
1353 msg_perror("can't open %s",ar_file
);
1357 setmode(archive
,O_BINARY
);
1362 /* this is a useless function that takes a buffer returned by wantbytes
1363 and does nothing with it. If the function called by wantbytes returns
1364 an error indicator (non-zero), this function is called for the rest of
1375 /* Some other routine wants SIZE bytes in the archive. For each chunk of
1376 the archive, call FUNC with the size of the chunk, and the address of
1377 the chunk it can work with.
1380 wantbytes(size
,func
)
1388 data
= findrec()->charptr
;
1389 if (data
== NULL
) { /* Check it... */
1390 msg("Unexpected EOF on archive file");
1393 data_size
= endofrecs()->charptr
- data
;
1396 if((*func
)(data_size
,data
))
1398 userec((union record
*)(data
+ data_size
- 1));
This page took 0.094334 seconds and 5 git commands to generate.