]>
Dogcows Code - chaz/tar/blob - src/buffer.c
1 /* Buffer management for tar.
2 Copyright (C) 1988 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.
25 * @(#) buffer.c 1.28 11/6/87 - gnu
30 #include <sys/types.h> /* For non-Berkeley systems */
35 #include <sys/ioctl.h>
36 #if !defined(USG) || defined(HAVE_MTIO)
46 # include <sys/inode.h>
48 # include <sys/file.h>
58 /* Either stdout or stderr: The thing we write messages (standard msgs, not
59 errors) to. Stdout unless we're writing a pipe, in which case stderr */
60 FILE *msg_file
= stdout
;
62 #define STDIN 0 /* Standard input file descriptor */
63 #define STDOUT 1 /* Standard output file descriptor */
65 #define PREAD 0 /* Read file descriptor from pipe() */
66 #define PWRITE 1 /* Write file descriptor from pipe() */
69 extern void *malloc();
70 extern void *valloc();
72 extern char *malloc();
73 extern char *valloc();
77 extern char *index(), *strcat();
78 extern char *strcpy();
81 * V7 doesn't have a #define for this.
96 #define MAGIC_STAT 105 /* Magic status returned by child, if
97 it can't exec. We hope compress/sh
98 never return this status! */
106 extern void finish_header();
107 extern void to_oct();
110 /* Obnoxious test to see if dimwit is trying to dump the archive */
116 * The record pointed to by save_rec should not be overlaid
117 * when reading in a new tape block. Copy it to record_save_area first, and
118 * change the pointer in *save_rec to point to record_save_area.
119 * Saved_recno records the record number at the time of the save.
120 * This is used by annofile() to print the record number of a file's
123 static union record
**save_rec
;
124 union record record_save_area
;
125 static long saved_recno
;
128 * PID of child program, if f_compress or remote archive access.
130 static int childpid
= 0;
133 * Record number of the start of this block of records
138 * Error recovery stuff
140 static int r_error_count
;
143 * Have we hit EOF yet?
147 /* JF we're reading, but we just read the last record and its time to update */
148 extern time_to_start_writing
;
149 int file_to_switch_to
= -1; /* If remote update, close archive, and use
150 this descriptor to write to */
152 static int volno
= 1; /* JF which volume of a multi-volume tape
155 char *save_name
= 0; /* Name of the file we are currently writing */
156 long save_totsize
; /* total size of file we are writing. Only
157 valid if save_name is non_zero */
158 long save_sizeleft
; /* Where we are in the file we are writing.
159 Only valid if save_name is non-zero */
161 int write_archive_to_stdout
;
163 /* Used by fl_read and fl_write to store the real info about saved names */
164 static char real_s_name
[NAMSIZ
];
165 static long real_s_totsize
;
166 static long real_s_sizeleft
;
168 /* Reset the EOF flag (if set), and re-set ar_record, etc */
176 ar_last
=ar_block
+blocking
;
182 * Return the location of the next available input or output record.
183 * Return NULL for EOF. Once we have returned NULL, we just keep returning
184 * it, to avoid accidentally going on to the next file on the "tape".
189 if (ar_record
== ar_last
) {
191 return (union record
*)NULL
; /* EOF */
193 if (ar_record
== ar_last
) {
195 return (union record
*)NULL
; /* EOF */
203 * Indicate that we have used all records up thru the argument.
204 * (should the arg have an off-by-1? XXX FIXME)
210 while(rec
>= ar_record
)
213 * Do NOT flush the archive here. If we do, the same
214 * argument to userec() could mean the next record (if the
215 * input block is exactly one record long), which is not what
218 if (ar_record
> ar_last
)
224 * Return a pointer to the end of the current records buffer.
225 * All the space between findrec() and endofrecs() is available
226 * for filling with data, or taking data from.
236 * Duplicate a file descriptor into a certain slot.
237 * Equivalent to BSD "dup2" with error reporting.
248 if(err
<0 && errno
!=EBADF
) {
249 msg_perror("Cannot close descriptor %d",to
);
254 msg_perror("cannot dup %s",msg
);
265 fprintf(stderr
,"MSDOS %s can't use compressed or remote archives\n",tar
);
285 msg_perror("cannot fork");
289 /* We're the parent. Clean up and be happy */
290 /* This, at least, is easy */
295 ck_close(pipe
[WRITE
]);
297 archive
= pipe
[WRITE
];
298 ck_close(pipe
[READ
]);
305 dupto(pipe
[WRITE
],STDOUT
,"(child) pipe to stdout");
306 ck_close(pipe
[READ
]);
308 dupto(pipe
[READ
],STDIN
,"(child) pipe to stdin");
309 ck_close(pipe
[WRITE
]);
312 /* We need a child tar only if
313 1: we're reading/writing stdin/out (to force reblocking)
314 2: the file is to be accessed by rmt (compress doesn't know how)
315 3: the file is not a plain file */
317 if(!(ar_file
[0]=='-' && ar_file
[1]=='\0') && isfile(ar_file
))
319 if(!(ar_file
[0]=='-' && ar_file
[1]=='\0') && !_remdev(ar_file
) && isfile(ar_file
))
322 /* We don't need a child tar. Open the archive */
324 archive
=open(ar_file
, O_RDONLY
|O_BINARY
, 0666);
326 msg_perror("can't open archive %s",ar_file
);
329 dupto(archive
,STDIN
,"archive to stdin");
330 /* close(archive); */
332 archive
=creat(ar_file
,0666);
334 msg_perror("can't open archive %s",ar_file
);
337 dupto(archive
,STDOUT
,"archive to stdout");
338 /* close(archive); */
341 /* We need a child tar */
346 msg_perror("child can't fork");
351 /* About to exec compress: set up the files */
353 dupto(kidpipe
[READ
],STDIN
,"((child)) pipe to stdin");
354 ck_close(kidpipe
[WRITE
]);
355 /* dup2(pipe[WRITE],STDOUT); */
357 /* dup2(pipe[READ],STDIN); */
358 dupto(kidpipe
[WRITE
],STDOUT
,"((child)) pipe to stdout");
359 ck_close(kidpipe
[READ
]);
361 /* ck_close(pipe[READ]); */
362 /* ck_close(pipe[WRITE]); */
363 /* ck_close(kidpipe[READ]);
364 ck_close(kidpipe[WRITE]); */
366 /* Grandchild. Do the right thing, namely sit here and
367 read/write the archive, and feed stuff back to compress */
370 dupto(kidpipe
[WRITE
],STDOUT
,"[child] pipe to stdout");
371 ck_close(kidpipe
[READ
]);
373 dupto(kidpipe
[READ
],STDIN
,"[child] pipe to stdin");
374 ck_close(kidpipe
[WRITE
]);
377 if (ar_file
[0] == '-' && ar_file
[1] == '\0') {
382 } else /* This can't happen if (ar_reading==2)
383 archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
384 else */if(ar_reading
)
385 archive
= rmtopen(ar_file
, O_RDONLY
|O_BINARY
, 0666);
387 archive
= rmtcreat(ar_file
, 0666);
390 msg_perror("can't open archive %s",ar_file
);
401 err
=rmtread(archive
, ar_block
->charptr
,(int)(blocksize
));
408 ptr
= ar_block
->charptr
;
411 count
= (max
<RECORDSIZE
) ? max
: RECORDSIZE
;
412 err
=write(STDOUT
,ptr
,count
);
415 msg_perror("can't write to compress");
418 msg("write to compress short %d bytes",count
-err
);
419 count
= (err
<0) ? 0 : err
;
431 ptr
= ar_block
->charptr
;
433 err
=read(STDIN
,ptr
,(n
<RECORDSIZE
) ? n
: RECORDSIZE
);
444 bzero(ar_block
->charptr
+blocksize
-n
,n
);
445 err
=rmtwrite(archive
,ar_block
->charptr
,blocksize
);
453 msg_perror("can't read from compress");
456 err
=rmtwrite(archive
, ar_block
->charptr
, (int)blocksize
);
462 /* close_archive(); */
466 /* So we should exec compress (-d) */
468 execlp("compress", "compress", "-d", (char *)0);
470 execlp("compress", "compress", (char *)0);
471 msg_perror("can't exec compress");
476 /* return non-zero if p is the name of a directory */
484 if((stbuf
.st_mode
&S_IFMT
)==S_IFREG
)
492 * Open an archive file. The argument specifies whether we are
493 * reading or writing.
495 /* JF if the arg is 2, open for reading and writing. */
496 open_archive(reading
)
499 msg_file
= f_exstdout
? stderr
: stdout
;
501 if (blocksize
== 0) {
502 msg("invalid value for blocksize");
507 msg("No archive name given, what should I do?");
513 ar_block
= (union record
*) valloc((unsigned)(blocksize
+(2*RECORDSIZE
)));
517 ar_block
= (union record
*) valloc((unsigned)blocksize
);
519 msg("could not allocate memory for blocking factor %d",
524 ar_record
= ar_block
;
525 ar_last
= ar_block
+ blocking
;
526 ar_reading
= reading
;
529 if(reading
==2 || f_verify
) {
530 msg("cannot update or verify compressed archives");
534 if(!reading
&& ar_file
[0]=='-' && ar_file
[1]=='\0')
536 /* child_open(rem_host, rem_file); */
537 } else if (ar_file
[0] == '-' && ar_file
[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_file
, O_RDWR
|O_CREAT
|O_BINARY
, 0666);
556 archive
= rmtopen(ar_file
, O_RDONLY
|O_BINARY
, 0666);
558 archive
= rmtcreat(ar_file
, 0666);
561 if(!_isrmt(archive
)) {
562 struct stat tmp_stat
;
564 fstat(archive
,&tmp_stat
);
565 if((tmp_stat
.st_mode
&S_IFMT
)==S_IFREG
) {
566 ar_dev
=tmp_stat
.st_dev
;
567 ar_ino
=tmp_stat
.st_ino
;
573 msg_perror("can't open %s",ar_file
);
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
.name
,
601 strlen (head
->header
.name
), 0, 0) < 0) {
602 msg ("Volume mismatch! %s!=%s", f_volhdr
,
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
.name
,"%s Volume 1",f_volhdr
);
620 strcpy(ar_block
->header
.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.
640 union record
**pointer
;
645 offset
= ar_record
- ar_block
;
646 saved_recno
= baserec
+ offset
;
650 * Perform a write to flush the buffer.
653 /*send_buffer_to_file();
655 deal_with_new_volume_stuff();
656 send_buffer_to_file();
664 static long bytes_written
= 0;
666 if(tape_length
&& bytes_written
>= tape_length
* 1024) {
670 err
= rmtwrite(archive
, ar_block
->charptr
,(int) blocksize
);
671 if(err
!=blocksize
&& !f_multivol
)
674 tot_written
+= blocksize
;
678 if (err
== blocksize
) {
687 if(save_name
[1]==':')
690 while(*save_name
=='/')
693 strcpy(real_s_name
,save_name
);
694 real_s_totsize
= save_totsize
;
695 real_s_sizeleft
= save_sizeleft
;
700 /* We're multivol Panic if we didn't get the right kind of response */
701 /* ENXIO is for the UNIX PC */
702 if(err
>0 || (err
<0 && errno
!=ENOSPC
&& errno
!=EIO
&& errno
!=ENXIO
))
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_file
);
790 msg("only wrote %u of %u bytes to %s",err
,blocksize
,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_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.
832 int err
; /* Result from system call */
833 int left
; /* Bytes left */
834 char *more
; /* Pointer to next byte to read */
837 * Clear the count of errors. This only applies to a single
838 * call to fl_read. We leave read_error_flag alone; it is
839 * only turned off by higher level software.
841 r_error_count
= 0; /* Clear error count */
844 * If we are about to wipe out a record that
845 * somebody needs to keep, copy it out to a holding
846 * area and adjust somebody's pointer to it.
849 *save_rec
>= ar_record
&&
850 *save_rec
< ar_last
) {
851 record_save_area
= **save_rec
;
852 *save_rec
= &record_save_area
;
854 if(write_archive_to_stdout
&& baserec
!=0) {
855 err
=rmtwrite(1, ar_block
->charptr
, blocksize
);
861 if(save_name
!=real_s_name
) {
863 if(save_name
[1]==':')
866 while(*save_name
=='/')
869 strcpy(real_s_name
,save_name
);
870 save_name
=real_s_name
;
872 real_s_totsize
= save_totsize
;
873 real_s_sizeleft
= save_sizeleft
;
883 err
= rmtread(archive
, ar_block
->charptr
, (int)blocksize
);
884 if (err
== blocksize
)
887 if((err
== 0 || (err
<0 && errno
==ENOSPC
)) && f_multivol
) {
891 if(new_volume((cmd_mode
==CMD_APPEND
|| cmd_mode
==CMD_CAT
|| cmd_mode
==CMD_UPDATE
) ? 2 : 1)<0)
894 err
= rmtread(archive
, ar_block
->charptr
,(int) blocksize
);
904 if(head
->header
.linkflag
==LF_VOLHDR
) {
909 ptr
=(char *)malloc(strlen(f_volhdr
)+20);
910 sprintf(ptr
,"%s Volume %d",f_volhdr
,volno
);
912 if (re_match (label_pattern
, head
->header
.name
,
913 strlen (head
->header
.name
),
915 msg("Volume mismatch! %s!=%s",f_volhdr
,
922 if(strcmp(ptr
,head
->header
.name
)) {
923 msg("Volume mismatch! %s!=%s",ptr
,head
->header
.name
);
932 fprintf(msg_file
,"Reading %s\n",head
->header
.name
);
934 } else if(f_volhdr
) {
935 msg("Warning: No volume header!");
941 if(head
->header
.linkflag
!=LF_MULTIVOL
|| strcmp(head
->header
.name
,real_s_name
)) {
942 msg("%s is not continued on this volume!",real_s_name
);
946 if(real_s_totsize
!=from_oct(1+12,head
->header
.size
)+from_oct(1+12,head
->header
.offset
)) {
947 msg("%s is the wrong size (%ld!=%ld+%ld)",
948 head
->header
.name
,save_totsize
,
949 from_oct(1+12,head
->header
.size
),
950 from_oct(1+12,head
->header
.offset
));
954 if(real_s_totsize
-real_s_sizeleft
!=from_oct(1+12,head
->header
.offset
)) {
955 msg("This volume is out of sequence");
963 } else if (err
< 0) {
965 goto error_loop
; /* Try again */
969 more
= ar_block
->charptr
+ err
;
970 left
= blocksize
- err
;
973 if (0 == (((unsigned)left
) % RECORDSIZE
)) {
974 /* FIXME, for size=0, multi vol support */
975 /* On the first block, warn about the problem */
976 if (!f_reblock
&& baserec
== 0 && f_verbose
&& err
> 0) {
977 /* msg("Blocksize = %d record%s",
978 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
979 msg("Blocksize = %d records", err
/ RECORDSIZE
);
981 ar_last
= ar_block
+ ((unsigned)(blocksize
- left
))/RECORDSIZE
;
986 * User warned us about this. Fix up.
990 err
= rmtread(archive
, more
, (int)left
);
993 goto error2loop
; /* Try again */
996 msg("archive %s EOF not on block boundary",ar_file
);
1004 msg("only read %d bytes from archive %s",err
,ar_file
);
1011 * Flush the current buffer to/from the archive.
1017 baserec
+= ar_last
- ar_block
; /* Keep track of block #s */
1018 ar_record
= ar_block
; /* Restore pointer to start */
1019 ar_last
= ar_block
+ blocking
; /* Restore pointer to end */
1022 if(time_to_start_writing
) {
1023 time_to_start_writing
=0;
1026 if(file_to_switch_to
>=0) {
1027 if((c
=rmtclose(archive
))<0)
1028 msg_perror("Warning: can't close %s(%d,%d)",ar_file
,archive
,c
);
1030 archive
=file_to_switch_to
;
1032 (void)backspace_output();
1041 /* Backspace the archive descriptor by one blocks worth.
1042 If its a tape, MTIOCTOP will work. If its something else,
1043 we try to seek on it. If we can't seek, we lose! */
1048 extern char *output_start
;
1055 if((rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1057 if(errno
==EIO
&& (rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1061 cur
=rmtlseek(archive
,0L,1);
1063 /* Seek back to the beginning of this block and
1064 start writing there. */
1066 if(rmtlseek(archive
,cur
,0)!=cur
) {
1067 /* Lseek failed. Try a different method */
1068 msg("Couldn't backspace archive file. It may be unreadable without -i.");
1069 /* Replace the first part of the block with nulls */
1070 if(ar_block
->charptr
!=output_start
)
1071 bzero(ar_block
->charptr
,output_start
-ar_block
->charptr
);
1079 * Close the archive file.
1087 if (time_to_start_writing
|| !ar_reading
)
1089 if(cmd_mode
==CMD_DELETE
) {
1092 pos
= rmtlseek(archive
,0L,1);
1094 /* FIXME does ftruncate really take an INT?! */
1095 (void) ftruncate(archive
,(int)pos
);
1097 (void)rmtwrite(archive
,"",0);
1103 if((c
=rmtclose(archive
))<0)
1104 msg_perror("Warning: can't close %s(%d,%d)",ar_file
,archive
,c
);
1109 * Loop waiting for the right child to die, or for
1112 while (((child
= wait(&status
)) != childpid
) && child
!= -1)
1116 switch (TERM_SIGNAL(status
)) {
1118 /* Child voluntarily terminated -- but why? */
1119 if (TERM_VALUE(status
) == MAGIC_STAT
) {
1120 exit(EX_SYSTEM
);/* Child had trouble */
1122 if (TERM_VALUE(status
) == (SIGPIPE
+ 128)) {
1124 * /bin/sh returns this if its child
1125 * dies with SIGPIPE. 'Sok.
1128 } else if (TERM_VALUE(status
))
1129 msg("child returned status %d",
1130 TERM_VALUE(status
));
1132 break; /* This is OK. */
1135 msg("child died with signal %d%s",
1136 TERM_SIGNAL(status
),
1137 TERM_COREDUMP(status
)? " (core dumped)": "");
1147 * Message management.
1149 * anno writes a message prefix on stream (eg stdout, stderr).
1151 * The specified prefix is normally output followed by a colon and a space.
1152 * However, if other command line options are set, more output can come
1153 * out, such as the record # within the archive.
1155 * If the specified prefix is NULL, no output is produced unless the
1156 * command line option(s) are set.
1158 * If the third argument is 1, the "saved" record # is used; if 0, the
1159 * "current" record # is used.
1162 anno(stream
, prefix
, savedp
)
1168 char buffer
[MAXANNO
]; /* Holds annorecment */
1169 # define ANNOWIDTH 13
1175 /* Make sure previous output gets out in sequence */
1176 if (stream
== stderr
)
1180 fputs(prefix
, stream
);
1183 offset
= ar_record
- ar_block
;
1184 (void) sprintf(buffer
, "rec %d: ",
1185 savedp
? saved_recno
:
1187 fputs(buffer
, stream
);
1188 space
= ANNOWIDTH
- strlen(buffer
);
1190 fprintf(stream
, "%*s", space
, "");
1192 } else if (prefix
) {
1193 fputs(prefix
, stream
);
1194 fputs(": ", stream
);
1200 /* We've hit the end of the old volume. Close it and open the next one */
1201 /* Values for type: 0: writing 1: reading 2: updating */
1208 static FILE *read_file
= 0;
1209 extern int now_verifying
;
1210 extern char TTY_NAME
[];
1213 if(!read_file
&& !f_run_script_at_end
)
1214 read_file
= (archive
==0) ? fopen(TTY_NAME
, "r") : stdin
;
1220 if((c
=rmtclose(archive
))<0)
1221 msg_perror("Warning: can't close %s(%d,%d)",ar_file
,archive
,c
);
1225 if (f_run_script_at_end
)
1226 system(info_script
);
1228 fprintf(msg_file
,"\007Prepare volume #%d and hit return: ",volno
);
1230 if(fgets(inbuf
,sizeof(inbuf
),read_file
)==0) {
1231 fprintf(msg_file
,"EOF? What does that mean?");
1232 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1233 msg("Warning: Archive is INCOMPLETE!");
1236 if(inbuf
[0]=='\n' || inbuf
[0]=='y' || inbuf
[0]=='Y')
1243 n [name] Give a new filename for the next (and subsequent) volume(s)\n\
1245 ! Spawn a subshell\n\
1246 ? Print this list\n");
1250 case 'q': /* Quit */
1251 fprintf(msg_file
,"No new volume; exiting.\n");
1252 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1253 msg("Warning: Archive is INCOMPLETE!");
1256 case 'n': /* Get new file name */
1259 static char *old_name
;
1261 for(q
= &inbuf
[1];*q
==' ' || *q
=='\t';q
++)
1268 old_name
=p
=(char *)malloc((unsigned)(strlen(q
)+2));
1270 msg("Can't allocate memory for name");
1280 spawnl(P_WAIT
,getenv("COMSPEC"),"-",0);
1282 /* JF this needs work! */
1285 msg_perror("can't fork!");
1289 if(p
==0) p
="/bin/sh";
1290 execlp(p
,"-sh","-i",0);
1291 msg_perror("can't exec a shell %s",p
);
1302 if(type
==2 || f_verify
)
1303 archive
=rmtopen(ar_file
,O_RDWR
|O_CREAT
,0666);
1305 archive
=rmtopen(ar_file
,O_RDONLY
,0666);
1307 archive
=rmtcreat(ar_file
,0666);
1312 msg_perror("can't open %s",ar_file
);
1316 setmode(archive
,O_BINARY
);
1321 /* this is a useless function that takes a buffer returned by wantbytes
1322 and does nothing with it. If the function called by wantbytes returns
1323 an error indicator (non-zero), this function is called for the rest of
1334 /* Some other routine wants SIZE bytes in the archive. For each chunk of
1335 the archive, call FUNC with the size of the chunk, and the address of
1336 the chunk it can work with.
1339 wantbytes(size
,func
)
1347 data
= findrec()->charptr
;
1348 if (data
== NULL
) { /* Check it... */
1349 msg("Unexpected EOF on archive file");
1352 data_size
= endofrecs()->charptr
- data
;
1355 if((*func
)(data_size
,data
))
1357 userec((union record
*)(data
+ data_size
- 1));
This page took 0.097185 seconds and 5 git commands to generate.