]>
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.
31 #include <sys/types.h> /* For non-Berkeley systems */
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 /* JF we're reading, but we just read the last record and its time to update */
131 extern time_to_start_writing
;
132 int file_to_switch_to
= -1; /* If remote update, close archive, and use
133 this descriptor to write to */
135 static int volno
= 1; /* JF which volume of a multi-volume tape
138 char *save_name
= 0; /* Name of the file we are currently writing */
139 long save_totsize
; /* total size of file we are writing. Only
140 valid if save_name is non_zero */
141 long save_sizeleft
; /* Where we are in the file we are writing.
142 Only valid if save_name is non-zero */
144 int write_archive_to_stdout
;
146 /* Used by fl_read and fl_write to store the real info about saved names */
147 static char real_s_name
[NAMSIZ
];
148 static long real_s_totsize
;
149 static long real_s_sizeleft
;
151 /* Reset the EOF flag (if set), and re-set ar_record, etc */
159 ar_last
=ar_block
+blocking
;
165 * Return the location of the next available input or output record.
166 * Return NULL for EOF. Once we have returned NULL, we just keep returning
167 * it, to avoid accidentally going on to the next file on the "tape".
172 if (ar_record
== ar_last
) {
174 return (union record
*)NULL
; /* EOF */
176 if (ar_record
== ar_last
) {
178 return (union record
*)NULL
; /* EOF */
186 * Indicate that we have used all records up thru the argument.
187 * (should the arg have an off-by-1? XXX FIXME)
193 while(rec
>= ar_record
)
196 * Do NOT flush the archive here. If we do, the same
197 * argument to userec() could mean the next record (if the
198 * input block is exactly one record long), which is not what
201 if (ar_record
> ar_last
)
207 * Return a pointer to the end of the current records buffer.
208 * All the space between findrec() and endofrecs() is available
209 * for filling with data, or taking data from.
219 * Duplicate a file descriptor into a certain slot.
220 * Equivalent to BSD "dup2" with error reporting.
231 if(err
<0 && errno
!=EBADF
) {
232 msg_perror("Cannot close descriptor %d",to
);
237 msg_perror("cannot dup %s",msg
);
248 fprintf(stderr
,"MS-DOS %s can't use compressed or remote archives\n",tar
);
268 msg_perror("cannot fork");
272 /* We're the parent. Clean up and be happy */
273 /* This, at least, is easy */
278 ck_close(pipe
[WRITE
]);
280 archive
= pipe
[WRITE
];
281 ck_close(pipe
[READ
]);
288 dupto(pipe
[WRITE
],STDOUT
,"(child) pipe to stdout");
289 ck_close(pipe
[READ
]);
291 dupto(pipe
[READ
],STDIN
,"(child) pipe to stdin");
292 ck_close(pipe
[WRITE
]);
295 /* We need a child tar only if
296 1: we're reading/writing stdin/out (to force reblocking)
297 2: the file is to be accessed by rmt (compress doesn't know how)
298 3: the file is not a plain file */
300 if(!(ar_file
[0]=='-' && ar_file
[1]=='\0') && isfile(ar_file
))
302 if(!(ar_file
[0]=='-' && ar_file
[1]=='\0') && !_remdev(ar_file
) && isfile(ar_file
))
305 /* We don't need a child tar. Open the archive */
307 archive
=open(ar_file
, O_RDONLY
|O_BINARY
, 0666);
309 msg_perror("can't open archive %s",ar_file
);
312 dupto(archive
,STDIN
,"archive to stdin");
313 /* close(archive); */
315 archive
=creat(ar_file
,0666);
317 msg_perror("can't open archive %s",ar_file
);
320 dupto(archive
,STDOUT
,"archive to stdout");
321 /* close(archive); */
324 /* We need a child tar */
329 msg_perror("child can't fork");
334 /* About to exec compress: set up the files */
336 dupto(kidpipe
[READ
],STDIN
,"((child)) pipe to stdin");
337 ck_close(kidpipe
[WRITE
]);
338 /* dup2(pipe[WRITE],STDOUT); */
340 /* dup2(pipe[READ],STDIN); */
341 dupto(kidpipe
[WRITE
],STDOUT
,"((child)) pipe to stdout");
342 ck_close(kidpipe
[READ
]);
344 /* ck_close(pipe[READ]); */
345 /* ck_close(pipe[WRITE]); */
346 /* ck_close(kidpipe[READ]);
347 ck_close(kidpipe[WRITE]); */
349 /* Grandchild. Do the right thing, namely sit here and
350 read/write the archive, and feed stuff back to compress */
353 dupto(kidpipe
[WRITE
],STDOUT
,"[child] pipe to stdout");
354 ck_close(kidpipe
[READ
]);
356 dupto(kidpipe
[READ
],STDIN
,"[child] pipe to stdin");
357 ck_close(kidpipe
[WRITE
]);
360 if (ar_file
[0] == '-' && ar_file
[1] == '\0') {
365 } else /* This can't happen if (ar_reading==2)
366 archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
367 else */if(ar_reading
)
368 archive
= rmtopen(ar_file
, O_RDONLY
|O_BINARY
, 0666);
370 archive
= rmtcreat(ar_file
, 0666);
373 msg_perror("can't open archive %s",ar_file
);
384 err
=rmtread(archive
, ar_block
->charptr
,(int)(blocksize
));
391 ptr
= ar_block
->charptr
;
394 count
= (max
<RECORDSIZE
) ? max
: RECORDSIZE
;
395 err
=write(STDOUT
,ptr
,count
);
398 msg_perror("can't write to compress");
401 msg("write to compress short %d bytes",count
-err
);
402 count
= (err
<0) ? 0 : err
;
414 ptr
= ar_block
->charptr
;
416 err
=read(STDIN
,ptr
,(n
<RECORDSIZE
) ? n
: RECORDSIZE
);
427 bzero(ar_block
->charptr
+blocksize
-n
,n
);
428 err
=rmtwrite(archive
,ar_block
->charptr
,blocksize
);
436 msg_perror("can't read from compress");
439 err
=rmtwrite(archive
, ar_block
->charptr
, (int)blocksize
);
445 /* close_archive(); */
449 /* So we should exec compress (-d) */
451 execlp("compress", "compress", "-d", (char *)0);
453 execlp("compress", "compress", (char *)0);
454 msg_perror("can't exec compress");
459 /* return non-zero if p is the name of a directory */
468 if(S_ISREG(stbuf
.st_mode
))
476 * Open an archive file. The argument specifies whether we are
477 * reading or writing.
479 /* JF if the arg is 2, open for reading and writing. */
481 open_archive(reading
)
484 msg_file
= f_exstdout
? stderr
: stdout
;
486 if (blocksize
== 0) {
487 msg("invalid value for blocksize");
492 msg("No archive name given, what should I do?");
498 ar_block
= (union record
*) valloc((unsigned)(blocksize
+(2*RECORDSIZE
)));
502 ar_block
= (union record
*) valloc((unsigned)blocksize
);
504 msg("could not allocate memory for blocking factor %d",
509 ar_record
= ar_block
;
510 ar_last
= ar_block
+ blocking
;
511 ar_reading
= reading
;
514 if(reading
==2 || f_verify
) {
515 msg("cannot update or verify compressed archives");
519 if(!reading
&& ar_file
[0]=='-' && ar_file
[1]=='\0')
521 /* child_open(rem_host, rem_file); */
522 } else if (ar_file
[0] == '-' && ar_file
[1] == '\0') {
523 f_reblock
++; /* Could be a pipe, be safe */
525 msg("can't verify stdin/stdout archive");
531 write_archive_to_stdout
++;
538 } else if (reading
==2 || f_verify
) {
539 archive
= rmtopen(ar_file
, O_RDWR
|O_CREAT
|O_BINARY
, 0666);
541 archive
= rmtopen(ar_file
, O_RDONLY
|O_BINARY
, 0666);
543 archive
= rmtcreat(ar_file
, 0666);
546 msg_perror("can't open %s",ar_file
);
550 if(!_isrmt(archive
)) {
551 struct stat tmp_stat
;
553 fstat(archive
,&tmp_stat
);
554 if(S_ISREG(tmp_stat
.st_mode
)) {
555 ar_dev
=tmp_stat
.st_dev
;
556 ar_ino
=tmp_stat
.st_ino
;
562 setmode(archive
, O_BINARY
);
566 ar_last
= ar_block
; /* Set up for 1st block = # 0 */
567 (void) findrec(); /* Read it in, check for EOF */
575 ptr
=malloc(strlen(f_volhdr
)+20);
576 sprintf(ptr
,"%s Volume %d",f_volhdr
,1);
582 msg("Archive not labelled to match %s",f_volhdr
);
585 if (re_match (label_pattern
, head
->header
.name
,
586 strlen (head
->header
.name
), 0, 0) < 0) {
587 msg ("Volume mismatch! %s!=%s", f_volhdr
,
592 if(strcmp(ptr
,head
->header
.name
)) {
593 msg("Volume mismatch! %s!=%s",ptr
,head
->header
.name
);
600 } else if(f_volhdr
) {
601 bzero((void *)ar_block
,RECORDSIZE
);
603 sprintf(ar_block
->header
.name
,"%s Volume 1",f_volhdr
);
605 strcpy(ar_block
->header
.name
,f_volhdr
);
606 ar_block
->header
.linkflag
= LF_VOLHDR
;
607 to_oct(time(0), 1+12, ar_block
->header
.mtime
);
608 finish_header(ar_block
);
615 * Remember a union record * as pointing to something that we
616 * need to keep when reading onward in the file. Only one such
617 * thing can be remembered at once, and it only works when reading
620 * We calculate "offset" then add it because some compilers end up
621 * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
622 * subtracting ar_block from that, shifting it back, losing the top 9 bits.
626 union record
**pointer
;
631 offset
= ar_record
- ar_block
;
632 saved_recno
= baserec
+ offset
;
636 * Perform a write to flush the buffer.
639 /*send_buffer_to_file();
641 deal_with_new_volume_stuff();
642 send_buffer_to_file();
651 static long bytes_written
= 0;
653 if(tape_length
&& bytes_written
>= tape_length
* 1024) {
657 err
= rmtwrite(archive
, ar_block
->charptr
,(int) blocksize
);
658 if(err
!=blocksize
&& !f_multivol
)
661 tot_written
+= blocksize
;
665 if (err
== blocksize
) {
674 if(save_name
[1]==':')
677 while(*save_name
=='/')
680 strcpy(real_s_name
,save_name
);
681 real_s_totsize
= save_totsize
;
682 real_s_sizeleft
= save_sizeleft
;
687 /* We're multivol Panic if we didn't get the right kind of response */
688 /* ENXIO is for the UNIX PC */
689 if(err
>0 || (err
<0 && errno
!=ENOSPC
&& errno
!=EIO
&& errno
!=ENXIO
))
695 if(f_volhdr
&& real_s_name
[0]) {
698 } else if(f_volhdr
|| real_s_name
[0]) {
704 bzero((void *)ar_block
,RECORDSIZE
);
705 sprintf(ar_block
->header
.name
,"%s Volume %d",f_volhdr
,volno
);
706 to_oct(time(0), 1+12, ar_block
->header
.mtime
);
707 ar_block
->header
.linkflag
= LF_VOLHDR
;
708 finish_header(ar_block
);
715 bzero((void *)ar_block
,RECORDSIZE
);
716 strcpy(ar_block
->header
.name
,real_s_name
);
717 ar_block
->header
.linkflag
= LF_MULTIVOL
;
718 to_oct((long)real_s_sizeleft
,1+12,
719 ar_block
->header
.size
);
720 to_oct((long)real_s_totsize
-real_s_sizeleft
,
721 1+12,ar_block
->header
.offset
);
724 finish_header(ar_block
);
730 err
= rmtwrite(archive
, ar_block
->charptr
,(int) blocksize
);
734 tot_written
+= blocksize
;
737 bytes_written
= blocksize
;
740 bcopy((void *)(ar_block
+blocking
-copy_back
),
742 copy_back
*RECORDSIZE
);
743 ar_record
+=copy_back
;
745 if(real_s_sizeleft
>=copy_back
*RECORDSIZE
)
746 real_s_sizeleft
-=copy_back
*RECORDSIZE
;
747 else if((real_s_sizeleft
+RECORDSIZE
-1)/RECORDSIZE
<=copy_back
)
748 real_s_name
[0] = '\0';
751 if(save_name
[1]==':')
754 while(*save_name
=='/')
757 strcpy(real_s_name
,save_name
);
758 real_s_sizeleft
= save_sizeleft
;
759 real_s_totsize
=save_totsize
;
765 /* Handle write errors on the archive. Write errors are always fatal */
766 /* Hitting the end of a volume does not cause a write error unless the write
767 * was the first block of the volume */
774 msg_perror("can't write to %s",ar_file
);
777 msg("only wrote %u of %u bytes to %s",err
,blocksize
,ar_file
);
783 * Handle read errors on the archive.
785 * If the read should be retried, readerror() returns to the caller.
790 # define READ_ERROR_MAX 10
792 read_error_flag
++; /* Tell callers */
794 msg_perror("read error on %s",ar_file
);
797 /* First block of tape. Probably stupidity error */
802 * Read error in mid archive. We retry up to READ_ERROR_MAX times
803 * and then give up on reading the archive. We set read_error_flag
804 * for our callers, so they can cope if they want.
806 if (r_error_count
++ > READ_ERROR_MAX
) {
807 msg("Too many errors, quitting.");
815 * Perform a read to flush the buffer.
820 int err
; /* Result from system call */
821 int left
; /* Bytes left */
822 char *more
; /* Pointer to next byte to read */
825 * Clear the count of errors. This only applies to a single
826 * call to fl_read. We leave read_error_flag alone; it is
827 * only turned off by higher level software.
829 r_error_count
= 0; /* Clear error count */
832 * If we are about to wipe out a record that
833 * somebody needs to keep, copy it out to a holding
834 * area and adjust somebody's pointer to it.
837 *save_rec
>= ar_record
&&
838 *save_rec
< ar_last
) {
839 record_save_area
= **save_rec
;
840 *save_rec
= &record_save_area
;
842 if(write_archive_to_stdout
&& baserec
!=0) {
843 err
=rmtwrite(1, ar_block
->charptr
, blocksize
);
849 if(save_name
!=real_s_name
) {
851 if(save_name
[1]==':')
854 while(*save_name
=='/')
857 strcpy(real_s_name
,save_name
);
858 save_name
=real_s_name
;
860 real_s_totsize
= save_totsize
;
861 real_s_sizeleft
= save_sizeleft
;
871 err
= rmtread(archive
, ar_block
->charptr
, (int)blocksize
);
872 if (err
== blocksize
)
875 if((err
== 0 || (err
<0 && errno
==ENOSPC
)) && f_multivol
) {
879 if(new_volume((cmd_mode
==CMD_APPEND
|| cmd_mode
==CMD_CAT
|| cmd_mode
==CMD_UPDATE
) ? 2 : 1)<0)
882 err
= rmtread(archive
, ar_block
->charptr
,(int) blocksize
);
892 if(head
->header
.linkflag
==LF_VOLHDR
) {
897 ptr
=(char *)malloc(strlen(f_volhdr
)+20);
898 sprintf(ptr
,"%s Volume %d",f_volhdr
,volno
);
900 if (re_match (label_pattern
, head
->header
.name
,
901 strlen (head
->header
.name
),
903 msg("Volume mismatch! %s!=%s",f_volhdr
,
910 if(strcmp(ptr
,head
->header
.name
)) {
911 msg("Volume mismatch! %s!=%s",ptr
,head
->header
.name
);
920 fprintf(msg_file
,"Reading %s\n",head
->header
.name
);
922 } else if(f_volhdr
) {
923 msg("Warning: No volume header!");
929 if(head
->header
.linkflag
!=LF_MULTIVOL
|| strcmp(head
->header
.name
,real_s_name
)) {
930 msg("%s is not continued on this volume!",real_s_name
);
934 if(real_s_totsize
!=from_oct(1+12,head
->header
.size
)+from_oct(1+12,head
->header
.offset
)) {
935 msg("%s is the wrong size (%ld!=%ld+%ld)",
936 head
->header
.name
,save_totsize
,
937 from_oct(1+12,head
->header
.size
),
938 from_oct(1+12,head
->header
.offset
));
942 if(real_s_totsize
-real_s_sizeleft
!=from_oct(1+12,head
->header
.offset
)) {
943 msg("This volume is out of sequence");
951 } else if (err
< 0) {
953 goto error_loop
; /* Try again */
957 more
= ar_block
->charptr
+ err
;
958 left
= blocksize
- err
;
961 if (0 == (((unsigned)left
) % RECORDSIZE
)) {
962 /* FIXME, for size=0, multi vol support */
963 /* On the first block, warn about the problem */
964 if (!f_reblock
&& baserec
== 0 && f_verbose
&& err
> 0) {
965 /* msg("Blocksize = %d record%s",
966 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
967 msg("Blocksize = %d records", err
/ RECORDSIZE
);
969 ar_last
= ar_block
+ ((unsigned)(blocksize
- left
))/RECORDSIZE
;
974 * User warned us about this. Fix up.
978 err
= rmtread(archive
, more
, (int)left
);
981 goto error2loop
; /* Try again */
984 msg("archive %s EOF not on block boundary",ar_file
);
992 msg("only read %d bytes from archive %s",err
,ar_file
);
999 * Flush the current buffer to/from the archive.
1006 baserec
+= ar_last
- ar_block
; /* Keep track of block #s */
1007 ar_record
= ar_block
; /* Restore pointer to start */
1008 ar_last
= ar_block
+ blocking
; /* Restore pointer to end */
1011 if(time_to_start_writing
) {
1012 time_to_start_writing
=0;
1015 if(file_to_switch_to
>=0) {
1016 if((c
=rmtclose(archive
))<0)
1017 msg_perror("Warning: can't close %s(%d,%d)",ar_file
,archive
,c
);
1019 archive
=file_to_switch_to
;
1021 (void)backspace_output();
1030 /* Backspace the archive descriptor by one blocks worth.
1031 If its a tape, MTIOCTOP will work. If its something else,
1032 we try to seek on it. If we can't seek, we lose! */
1038 extern char *output_start
;
1045 if((rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1047 if(errno
==EIO
&& (rmtioctl(archive
,MTIOCTOP
,&t
))>=0)
1051 cur
=rmtlseek(archive
,0L,1);
1053 /* Seek back to the beginning of this block and
1054 start writing there. */
1056 if(rmtlseek(archive
,cur
,0)!=cur
) {
1057 /* Lseek failed. Try a different method */
1058 msg("Couldn't backspace archive file. It may be unreadable without -i.");
1059 /* Replace the first part of the block with nulls */
1060 if(ar_block
->charptr
!=output_start
)
1061 bzero(ar_block
->charptr
,output_start
-ar_block
->charptr
);
1069 * Close the archive file.
1078 if (time_to_start_writing
|| !ar_reading
)
1080 if(cmd_mode
==CMD_DELETE
) {
1083 pos
= rmtlseek(archive
,0L,1);
1085 (void) ftruncate(archive
,pos
);
1087 (void)rmtwrite(archive
,"",0);
1093 if((c
=rmtclose(archive
))<0)
1094 msg_perror("Warning: can't close %s(%d,%d)",ar_file
,archive
,c
);
1099 * Loop waiting for the right child to die, or for
1102 while (((child
= wait(&status
)) != childpid
) && child
!= -1)
1106 switch (WTERMSIG(status
)) {
1108 /* Child voluntarily terminated -- but why? */
1109 if (WEXITSTATUS(status
) == MAGIC_STAT
) {
1110 exit(EX_SYSTEM
);/* Child had trouble */
1112 if (WEXITSTATUS(status
) == (SIGPIPE
+ 128)) {
1114 * /bin/sh returns this if its child
1115 * dies with SIGPIPE. 'Sok.
1118 } else if (WEXITSTATUS(status
))
1119 msg("child returned status %d",
1120 WEXITSTATUS(status
));
1122 break; /* This is OK. */
1125 msg("child died with signal %d%s",
1127 WIFCOREDUMPED(status
)? " (core dumped)": "");
1131 #endif /* __MSDOS__ */
1137 * Message management.
1139 * anno writes a message prefix on stream (eg stdout, stderr).
1141 * The specified prefix is normally output followed by a colon and a space.
1142 * However, if other command line options are set, more output can come
1143 * out, such as the record # within the archive.
1145 * If the specified prefix is NULL, no output is produced unless the
1146 * command line option(s) are set.
1148 * If the third argument is 1, the "saved" record # is used; if 0, the
1149 * "current" record # is used.
1152 anno(stream
, prefix
, savedp
)
1158 char buffer
[MAXANNO
]; /* Holds annorecment */
1159 # define ANNOWIDTH 13
1165 /* Make sure previous output gets out in sequence */
1166 if (stream
== stderr
)
1170 fputs(prefix
, stream
);
1173 offset
= ar_record
- ar_block
;
1174 (void) sprintf(buffer
, "rec %d: ",
1175 savedp
? saved_recno
:
1177 fputs(buffer
, stream
);
1178 space
= ANNOWIDTH
- strlen(buffer
);
1180 fprintf(stream
, "%*s", space
, "");
1182 } else if (prefix
) {
1183 fputs(prefix
, stream
);
1184 fputs(": ", stream
);
1190 /* We've hit the end of the old volume. Close it and open the next one */
1191 /* Values for type: 0: writing 1: reading 2: updating */
1199 static FILE *read_file
= 0;
1200 extern int now_verifying
;
1201 extern char TTY_NAME
[];
1204 if(!read_file
&& !f_run_script_at_end
)
1205 read_file
= (archive
==0) ? fopen(TTY_NAME
, "r") : stdin
;
1211 if((c
=rmtclose(archive
))<0)
1212 msg_perror("Warning: can't close %s(%d,%d)",ar_file
,archive
,c
);
1216 if (f_run_script_at_end
)
1217 system(info_script
);
1219 fprintf(msg_file
,"\007Prepare volume #%d and hit return: ",volno
);
1221 if(fgets(inbuf
,sizeof(inbuf
),read_file
)==0) {
1222 fprintf(msg_file
,"EOF? What does that mean?");
1223 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1224 msg("Warning: Archive is INCOMPLETE!");
1227 if(inbuf
[0]=='\n' || inbuf
[0]=='y' || inbuf
[0]=='Y')
1234 n [name] Give a new filename for the next (and subsequent) volume(s)\n\
1236 ! Spawn a subshell\n\
1237 ? Print this list\n");
1241 case 'q': /* Quit */
1242 fprintf(msg_file
,"No new volume; exiting.\n");
1243 if(cmd_mode
!=CMD_EXTRACT
&& cmd_mode
!=CMD_LIST
&& cmd_mode
!=CMD_DIFF
)
1244 msg("Warning: Archive is INCOMPLETE!");
1247 case 'n': /* Get new file name */
1250 static char *old_name
;
1252 for(q
= &inbuf
[1];*q
==' ' || *q
=='\t';q
++)
1259 old_name
=p
=(char *)malloc((unsigned)(strlen(q
)+2));
1261 msg("Can't allocate memory for name");
1271 spawnl(P_WAIT
,getenv("COMSPEC"),"-",0);
1273 /* JF this needs work! */
1276 msg_perror("can't fork!");
1280 if(p
==0) p
="/bin/sh";
1281 execlp(p
,"-sh","-i",0);
1282 msg_perror("can't exec a shell %s",p
);
1293 if(type
==2 || f_verify
)
1294 archive
=rmtopen(ar_file
,O_RDWR
|O_CREAT
,0666);
1296 archive
=rmtopen(ar_file
,O_RDONLY
,0666);
1298 archive
=rmtcreat(ar_file
,0666);
1303 msg_perror("can't open %s",ar_file
);
1307 setmode(archive
,O_BINARY
);
1312 /* this is a useless function that takes a buffer returned by wantbytes
1313 and does nothing with it. If the function called by wantbytes returns
1314 an error indicator (non-zero), this function is called for the rest of
1325 /* Some other routine wants SIZE bytes in the archive. For each chunk of
1326 the archive, call FUNC with the size of the chunk, and the address of
1327 the chunk it can work with.
1330 wantbytes(size
,func
)
1338 data
= findrec()->charptr
;
1339 if (data
== NULL
) { /* Check it... */
1340 msg("Unexpected EOF on archive file");
1343 data_size
= endofrecs()->charptr
- data
;
1346 if((*func
)(data_size
,data
))
1348 userec((union record
*)(data
+ data_size
- 1));
This page took 0.094095 seconds and 5 git commands to generate.