]>
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_files
[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_files
[0][0] == '-' && ar_files
[0][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
;
518 if (f_multivol
&& f_verify
)
520 msg ("cannot verify multi-volume archives");
525 if(reading
==2 || f_verify
) {
526 msg("cannot update or verify compressed archives");
530 msg ("cannot use multi-volume compressed archives");
534 if(!reading
&& ar_files
[0][0]=='-' && ar_files
[0][1]=='\0')
536 /* child_open(rem_host, rem_file); */
537 } else if (ar_files
[0][0] == '-' && ar_files
[0][1] == '\0') {
538 f_reblock
++; /* Could be a pipe, be safe */
540 msg("can't verify stdin/stdout archive");
546 write_archive_to_stdout
++;
553 } else if (reading
==2 || f_verify
) {
554 archive
= rmtopen(ar_files
[0], O_RDWR
|O_CREAT
|O_BINARY
, 0666);
556 archive
= rmtopen(ar_files
[0], O_RDONLY
|O_BINARY
, 0666);
558 archive
= rmtcreat(ar_files
[0], 0666);
561 msg_perror("can't open %s",ar_files
[0]);
565 if(!_isrmt(archive
)) {
566 struct stat tmp_stat
;
568 fstat(archive
,&tmp_stat
);
569 if(S_ISREG(tmp_stat
.st_mode
)) {
570 ar_dev
=tmp_stat
.st_dev
;
571 ar_ino
=tmp_stat
.st_ino
;
577 setmode(archive
, O_BINARY
);
581 ar_last
= ar_block
; /* Set up for 1st block = # 0 */
582 (void) findrec(); /* Read it in, check for EOF */
590 ptr
=malloc(strlen(f_volhdr
)+20);
591 sprintf(ptr
,"%s Volume %d",f_volhdr
,1);
597 msg("Archive not labelled to match %s",f_volhdr
);
600 if (re_match (label_pattern
, head
->header
.arch_name
,
601 strlen (head
->header
.arch_name
), 0, 0) < 0) {
602 msg ("Volume mismatch! %s!=%s", f_volhdr
,
603 head
->header
.arch_name
);
607 if(strcmp(ptr
,head
->header
.name
)) {
608 msg("Volume mismatch! %s!=%s",ptr
,head
->header
.name
);
615 } else if(f_volhdr
) {
616 bzero((void *)ar_block
,RECORDSIZE
);
618 sprintf(ar_block
->header
.arch_name
,"%s Volume 1",f_volhdr
);
620 strcpy(ar_block
->header
.arch_name
,f_volhdr
);
621 ar_block
->header
.linkflag
= LF_VOLHDR
;
622 to_oct(time(0), 1+12, ar_block
->header
.mtime
);
623 finish_header(ar_block
);
630 * Remember a union record * as pointing to something that we
631 * need to keep when reading onward in the file. Only one such
632 * thing can be remembered at once, and it only works when reading
635 * We calculate "offset" then add it because some compilers end up
636 * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
637 * subtracting ar_block from that, shifting it back, losing the top 9 bits.
641 union record
**pointer
;
646 offset
= ar_record
- ar_block
;
647 saved_recno
= baserec
+ offset
;
651 * Perform a write to flush the buffer.
654 /*send_buffer_to_file();
656 deal_with_new_volume_stuff();
657 send_buffer_to_file();
666 static long bytes_written
= 0;
668 if (f_checkpoint
&& ! (++checkpoint
% 10))
669 msg ("Write checkpoint %d\n", checkpoint
);
670 if(tape_length
&& bytes_written
>= tape_length
* 1024) {
674 err
= rmtwrite(archive
, ar_block
->charptr
,(int) blocksize
);
675 if(err
!=blocksize
&& !f_multivol
)
678 tot_written
+= blocksize
;
682 if (err
== blocksize
) {
691 if(save_name
[1]==':')
694 while(*save_name
=='/')
697 strcpy(real_s_name
,save_name
);
698 real_s_totsize
= save_totsize
;
699 real_s_sizeleft
= save_sizeleft
;
704 /* We're multivol Panic if we didn't get the right kind of response */
705 /* ENXIO is for the UNIX PC */
706 if(err
<0 && errno
!=ENOSPC
&& errno
!=EIO
&& errno
!=ENXIO
)
709 /* If error indicates a short write, we just move to the next tape. */
714 if(f_volhdr
&& real_s_name
[0]) {
717 } else if(f_volhdr
|| real_s_name
[0]) {
723 bzero((void *)ar_block
,RECORDSIZE
);
724 sprintf(ar_block
->header
.arch_name
,"%s Volume %d",f_volhdr
,volno
);
725 to_oct(time(0), 1+12, ar_block
->header
.mtime
);
726 ar_block
->header
.linkflag
= LF_VOLHDR
;
727 finish_header(ar_block
);
734 bzero((void *)ar_block
,RECORDSIZE
);
735 strcpy(ar_block
->header
.arch_name
,real_s_name
);
736 ar_block
->header
.linkflag
= LF_MULTIVOL
;
737 to_oct((long)real_s_sizeleft
,1+12,
738 ar_block
->header
.size
);
739 to_oct((long)real_s_totsize
-real_s_sizeleft
,
740 1+12,ar_block
->header
.offset
);
743 finish_header(ar_block
);
749 err
= rmtwrite(archive
, ar_block
->charptr
,(int) blocksize
);
753 tot_written
+= blocksize
;
756 bytes_written
= blocksize
;
759 bcopy((void *)(ar_block
+blocking
-copy_back
),
761 copy_back
*RECORDSIZE
);
762 ar_record
+=copy_back
;
764 if(real_s_sizeleft
>=copy_back
*RECORDSIZE
)
765 real_s_sizeleft
-=copy_back
*RECORDSIZE
;
766 else if((real_s_sizeleft
+RECORDSIZE
-1)/RECORDSIZE
<=copy_back
)
767 real_s_name
[0] = '\0';
770 if(save_name
[1]==':')
773 while(*save_name
=='/')
776 strcpy(real_s_name
,save_name
);
777 real_s_sizeleft
= save_sizeleft
;
778 real_s_totsize
=save_totsize
;
784 /* Handle write errors on the archive. Write errors are always fatal */
785 /* Hitting the end of a volume does not cause a write error unless the write
786 * was the first block of the volume */
793 msg_perror("can't write to %s",ar_files
[cur_ar_file
]);
796 msg("only wrote %u of %u bytes to %s",err
,blocksize
,ar_files
[cur_ar_file
]);
802 * Handle read errors on the archive.
804 * If the read should be retried, readerror() returns to the caller.
809 # define READ_ERROR_MAX 10
811 read_error_flag
++; /* Tell callers */
813 msg_perror("read error on %s",ar_files
[cur_ar_file
]);
816 /* First block of tape. Probably stupidity error */
821 * Read error in mid archive. We retry up to READ_ERROR_MAX times
822 * and then give up on reading the archive. We set read_error_flag
823 * for our callers, so they can cope if they want.
825 if (r_error_count
++ > READ_ERROR_MAX
) {
826 msg("Too many errors, quitting.");
834 * Perform a read to flush the buffer.
839 int err
; /* Result from system call */
840 int left
; /* Bytes left */
841 char *more
; /* Pointer to next byte to read */
843 if (f_checkpoint
&& ! (++checkpoint
% 10))
844 msg ("Read checkpoint %d\n", checkpoint
);
847 * Clear the count of errors. This only applies to a single
848 * call to fl_read. We leave read_error_flag alone; it is
849 * only turned off by higher level software.
851 r_error_count
= 0; /* Clear error count */
854 * If we are about to wipe out a record that
855 * somebody needs to keep, copy it out to a holding
856 * area and adjust somebody's pointer to it.
859 *save_rec
>= ar_record
&&
860 *save_rec
< ar_last
) {
861 record_save_area
= **save_rec
;
862 *save_rec
= &record_save_area
;
864 if(write_archive_to_stdout
&& baserec
!=0) {
865 err
=rmtwrite(1, ar_block
->charptr
, blocksize
);
871 if(save_name
!=real_s_name
) {
873 if(save_name
[1]==':')
876 while(*save_name
=='/')
879 strcpy(real_s_name
,save_name
);
880 save_name
=real_s_name
;
882 real_s_totsize
= save_totsize
;
883 real_s_sizeleft
= save_sizeleft
;
893 err
= rmtread(archive
, ar_block
->charptr
, (int)blocksize
);
894 if (err
== blocksize
)
897 if((err
== 0 || (err
<0 && errno
==ENOSPC
) || (err
> 0 && !f_reblock
)) && f_multivol
) {
901 if(new_volume((cmd_mode
==CMD_APPEND
|| cmd_mode
==CMD_CAT
|| cmd_mode
==CMD_UPDATE
) ? 2 : 1)<0)
904 err
= rmtread(archive
, ar_block
->charptr
,(int) blocksize
);
914 if(head
->header
.linkflag
==LF_VOLHDR
) {
919 ptr
=(char *)malloc(strlen(f_volhdr
)+20);
920 sprintf(ptr
,"%s Volume %d",f_volhdr
,volno
);
922 if (re_match (label_pattern
, head
->header
.arch_name
,
923 strlen (head
->header
.arch_name
),
925 msg("Volume mismatch! %s!=%s",f_volhdr
,
926 head
->header
.arch_name
);
933 if(strcmp(ptr
,head
->header
.name
)) {
934 msg("Volume mismatch! %s!=%s",ptr
,head
->header
.name
);
944 fprintf(msg_file
,"Reading %s\n",head
->header
.arch_name
);
946 } else if(f_volhdr
) {
947 msg("Warning: No volume header!");
953 if(head
->header
.linkflag
!=LF_MULTIVOL
|| strcmp(head
->header
.arch_name
,real_s_name
)) {
954 msg("%s is not continued on this volume!",real_s_name
);
959 if(real_s_totsize
!=from_oct(1+12,head
->header
.size
)+from_oct(1+12,head
->header
.offset
)) {
960 msg("%s is the wrong size (%ld!=%ld+%ld)",
961 head
->header
.arch_name
,save_totsize
,
962 from_oct(1+12,head
->header
.size
),
963 from_oct(1+12,head
->header
.offset
));
968 if(real_s_totsize
-real_s_sizeleft
!=from_oct(1+12,head
->header
.offset
)) {
969 msg("This volume is out of sequence");
978 } else if (err
< 0) {
980 goto error_loop
; /* Try again */
984 more
= ar_block
->charptr
+ err
;
985 left
= blocksize
- err
;
988 if (0 == (((unsigned)left
) % RECORDSIZE
)) {
989 /* FIXME, for size=0, multi vol support */
990 /* On the first block, warn about the problem */
991 if (!f_reblock
&& baserec
== 0 && f_verbose
&& err
> 0) {
992 /* msg("Blocksize = %d record%s",
993 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
994 msg("Blocksize = %d records", err
/ RECORDSIZE
);
996 ar_last
= ar_block
+ ((unsigned)(blocksize
- left
))/RECORDSIZE
;
1001 * User warned us about this. Fix up.
1005 err
= rmtread(archive
, more
, (int)left
);
1008 goto error2loop
; /* Try again */
1011 msg("archive %s EOF not on block boundary",ar_files
[cur_ar_file
]);
1019 msg("only read %d bytes from archive %s",err
,ar_files
[cur_ar_file
]);
1026 * Flush the current buffer to/from the archive.
1033 baserec
+= ar_last
- ar_block
; /* Keep track of block #s */
1034 ar_record
= ar_block
; /* Restore pointer to start */
1035 ar_last
= ar_block
+ blocking
; /* Restore pointer to end */
1038 if(time_to_start_writing
) {
1039 time_to_start_writing
=0;
1042 if(file_to_switch_to
>=0) {
1043 if((c
=rmtclose(archive
))<0)
1044 msg_perror("Warning: can't close %s(%d,%d)",ar_files
[cur_ar_file
],archive
,c
);
1046 archive
=file_to_switch_to
;
1048 (void)backspace_output();
1057 /* Backspace the archive descriptor by one blocks worth.
1058 If its a tape, MTIOCTOP will work. If its something else,
1059 we try to seek on it. If we can't seek, we lose! */
1065 extern char *output_start
;
1072 if((rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1074 if(errno
==EIO
&& (rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1078 cur
=rmtlseek(archive
,0L,1);
1080 /* Seek back to the beginning of this block and
1081 start writing there. */
1083 if(rmtlseek(archive
,cur
,0)!=cur
) {
1084 /* Lseek failed. Try a different method */
1085 msg("Couldn't backspace archive file. It may be unreadable without -i.");
1086 /* Replace the first part of the block with nulls */
1087 if(ar_block
->charptr
!=output_start
)
1088 bzero(ar_block
->charptr
,output_start
-ar_block
->charptr
);
1096 * Close the archive file.
1105 if (time_to_start_writing
|| !ar_reading
)
1107 if(cmd_mode
==CMD_DELETE
) {
1110 pos
= rmtlseek(archive
,0L,1);
1112 (void) ftruncate(archive
,pos
);
1114 (void)rmtwrite(archive
,"",0);
1120 if((c
=rmtclose(archive
))<0)
1121 msg_perror("Warning: can't close %s(%d,%d)",ar_files
[cur_ar_file
],archive
,c
);
1126 * Loop waiting for the right child to die, or for
1129 while (((child
= wait(&status
)) != childpid
) && child
!= -1)
1134 if (WIFSIGNALED(status
))
1136 /* SIGPIPE is OK, everything else is a problem. */
1137 if (WTERMSIG (status
) != SIGPIPE
)
1138 msg("child died with signal %d%s", WTERMSIG(status
),
1139 WIFCOREDUMPED(status
)? " (core dumped)": "");
1143 /* Child voluntarily terminated -- but why? */
1144 if (WEXITSTATUS(status
) == MAGIC_STAT
) {
1145 exit(EX_SYSTEM
);/* Child had trouble */
1147 if (WEXITSTATUS(status
) == (SIGPIPE
+ 128)) {
1149 * /bin/sh returns this if its child
1150 * dies with SIGPIPE. 'Sok.
1153 } else if (WEXITSTATUS(status
))
1154 msg("child returned status %d",
1155 WEXITSTATUS(status
));
1159 #endif /* __MSDOS__ */
1165 * Message management.
1167 * anno writes a message prefix on stream (eg stdout, stderr).
1169 * The specified prefix is normally output followed by a colon and a space.
1170 * However, if other command line options are set, more output can come
1171 * out, such as the record # within the archive.
1173 * If the specified prefix is NULL, no output is produced unless the
1174 * command line option(s) are set.
1176 * If the third argument is 1, the "saved" record # is used; if 0, the
1177 * "current" record # is used.
1180 anno(stream
, prefix
, savedp
)
1186 char buffer
[MAXANNO
]; /* Holds annorecment */
1187 # define ANNOWIDTH 13
1193 /* Make sure previous output gets out in sequence */
1194 if (stream
== stderr
)
1198 fputs(prefix
, stream
);
1201 offset
= ar_record
- ar_block
;
1202 (void) sprintf(buffer
, "rec %d: ",
1203 savedp
? saved_recno
:
1205 fputs(buffer
, stream
);
1206 space
= ANNOWIDTH
- strlen(buffer
);
1208 fprintf(stream
, "%*s", space
, "");
1210 } else if (prefix
) {
1211 fputs(prefix
, stream
);
1212 fputs(": ", stream
);
1218 /* Called to initialize the global volume number. */
1220 init_volume_number ()
1224 vf
= fopen (f_volno_file
, "r");
1225 if (!vf
&& errno
!= ENOENT
)
1226 msg_perror ("%s", f_volno_file
);
1230 fscanf (vf
, "%d", &global_volno
);
1235 /* Called to write out the closing global volume number. */
1237 closeout_volume_number ()
1241 vf
= fopen (f_volno_file
, "w");
1243 msg_perror ("%s", f_volno_file
);
1246 fprintf (vf
, "%d\n", global_volno
);
1251 /* We've hit the end of the old volume. Close it and open the next one */
1252 /* Values for type: 0: writing 1: reading 2: updating */
1260 static FILE *read_file
= 0;
1261 extern int now_verifying
;
1262 extern char TTY_NAME
[];
1263 static int looped
= 0;
1265 if(!read_file
&& !f_run_script_at_end
)
1266 read_file
= (archive
==0) ? fopen(TTY_NAME
, "r") : stdin
;
1272 if((c
=rmtclose(archive
))<0)
1273 msg_perror("Warning: can't close %s(%d,%d)",ar_files
[cur_ar_file
],archive
,c
);
1278 if (cur_ar_file
== n_ar_files
)
1287 /* We have to prompt from now on. */
1288 if (f_run_script_at_end
)
1289 system(info_script
);
1291 fprintf(msg_file
,"\007Prepare volume #%d for %s and hit return: ",global_volno
, ar_files
[cur_ar_file
]);
1293 if(fgets(inbuf
,sizeof(inbuf
),read_file
)==0) {
1294 fprintf(msg_file
,"EOF? What does that mean?");
1295 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1296 msg("Warning: Archive is INCOMPLETE!");
1299 if(inbuf
[0]=='\n' || inbuf
[0]=='y' || inbuf
[0]=='Y')
1306 n [name] Give a new filename for the next (and subsequent) volume(s)\n\
1308 ! Spawn a subshell\n\
1309 ? Print this list\n");
1313 case 'q': /* Quit */
1314 fprintf(msg_file
,"No new volume; exiting.\n");
1315 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1316 msg("Warning: Archive is INCOMPLETE!");
1319 case 'n': /* Get new file name */
1322 static char *old_name
;
1324 for(q
= &inbuf
[1];*q
==' ' || *q
=='\t';q
++)
1329 old_name
=p
=(char *)malloc((unsigned)(strlen(q
)+2));
1331 msg("Can't allocate memory for name");
1335 ar_files
[cur_ar_file
]=p
;
1341 spawnl(P_WAIT
,getenv("COMSPEC"),"-",0);
1343 /* JF this needs work! */
1346 msg_perror("can't fork!");
1350 if(p
==0) p
="/bin/sh";
1351 execlp(p
,"-sh","-i",0);
1352 msg_perror("can't exec a shell %s",p
);
1365 if(type
==2 || f_verify
)
1366 archive
=rmtopen(ar_files
[cur_ar_file
],O_RDWR
|O_CREAT
,0666);
1368 archive
=rmtopen(ar_files
[cur_ar_file
],O_RDONLY
,0666);
1370 archive
=rmtcreat(ar_files
[cur_ar_file
],0666);
1375 msg_perror("can't open %s",ar_files
[cur_ar_file
]);
1379 setmode(archive
,O_BINARY
);
1384 /* this is a useless function that takes a buffer returned by wantbytes
1385 and does nothing with it. If the function called by wantbytes returns
1386 an error indicator (non-zero), this function is called for the rest of
1397 /* Some other routine wants SIZE bytes in the archive. For each chunk of
1398 the archive, call FUNC with the size of the chunk, and the address of
1399 the chunk it can work with.
1402 wantbytes(size
,func
)
1410 data
= findrec()->charptr
;
1411 if (data
== NULL
) { /* Check it... */
1412 msg("Unexpected EOF on archive file");
1415 data_size
= endofrecs()->charptr
- data
;
1418 if((*func
)(data_size
,data
))
1420 userec((union record
*)(data
+ data_size
- 1));
This page took 0.094543 seconds and 5 git commands to generate.