|
@@ -1,5 +1,5 @@
|
|
|
/* Buffer management for tar.
|
|
|
- Copyright (C) 1988, 1992 Free Software Foundation
|
|
|
+ Copyright (C) 1988 Free Software Foundation
|
|
|
|
|
|
This file is part of GNU Tar.
|
|
|
|
|
@@ -21,38 +21,34 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
* Buffer management for tar.
|
|
|
*
|
|
|
* Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
|
|
|
+ *
|
|
|
+ * @(#) buffer.c 1.28 11/6/87 - gnu
|
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
|
#include <errno.h>
|
|
|
-#ifndef STDC_HEADERS
|
|
|
-extern int errno;
|
|
|
-#endif
|
|
|
#include <sys/types.h> /* For non-Berkeley systems */
|
|
|
+#include <sys/stat.h>
|
|
|
#include <signal.h>
|
|
|
-#include <time.h>
|
|
|
-time_t time();
|
|
|
|
|
|
-#ifdef HAVE_SYS_MTIO_H
|
|
|
+#ifndef MSDOS
|
|
|
#include <sys/ioctl.h>
|
|
|
+#if !defined(USG) || defined(HAVE_MTIO)
|
|
|
#include <sys/mtio.h>
|
|
|
#endif
|
|
|
-
|
|
|
-#ifdef BSD42
|
|
|
-#include <sys/file.h>
|
|
|
-#else
|
|
|
-#ifndef V7
|
|
|
-#include <fcntl.h>
|
|
|
-#endif
|
|
|
#endif
|
|
|
|
|
|
-#ifdef __MSDOS__
|
|
|
+#ifdef MSDOS
|
|
|
+# include <fcntl.h>
|
|
|
#include <process.h>
|
|
|
+#else
|
|
|
+# ifdef XENIX
|
|
|
+# include <sys/inode.h>
|
|
|
+# endif
|
|
|
+# include <sys/file.h>
|
|
|
#endif
|
|
|
|
|
|
-#ifdef XENIX
|
|
|
-#include <sys/inode.h>
|
|
|
-#endif
|
|
|
+extern int errno;
|
|
|
|
|
|
#include "tar.h"
|
|
|
#include "port.h"
|
|
@@ -69,24 +65,45 @@ FILE *msg_file = stdout;
|
|
|
#define PREAD 0 /* Read file descriptor from pipe() */
|
|
|
#define PWRITE 1 /* Write file descriptor from pipe() */
|
|
|
|
|
|
+#ifdef __STDC__
|
|
|
+extern void *malloc();
|
|
|
+extern void *valloc();
|
|
|
+#else
|
|
|
+extern char *malloc();
|
|
|
+extern char *valloc();
|
|
|
+#endif
|
|
|
+extern time_t time();
|
|
|
+
|
|
|
+extern char *index(), *strcat();
|
|
|
+extern char *strcpy();
|
|
|
+
|
|
|
+/*
|
|
|
+ * V7 doesn't have a #define for this.
|
|
|
+ */
|
|
|
+#ifndef O_RDONLY
|
|
|
+#define O_RDONLY 0
|
|
|
+#endif
|
|
|
+#ifndef O_RDWR
|
|
|
+#define O_RDWR 2
|
|
|
+#endif
|
|
|
+#ifndef O_CREAT
|
|
|
+#define O_CREAT 0
|
|
|
+#endif
|
|
|
+#ifndef O_BINARY
|
|
|
+#define O_BINARY 0
|
|
|
+#endif
|
|
|
+
|
|
|
#define MAGIC_STAT 105 /* Magic status returned by child, if
|
|
|
it can't exec. We hope compress/sh
|
|
|
never return this status! */
|
|
|
|
|
|
-char *valloc();
|
|
|
-
|
|
|
void writeerror();
|
|
|
void readerror();
|
|
|
|
|
|
void ck_pipe();
|
|
|
void ck_close();
|
|
|
|
|
|
-int backspace_output();
|
|
|
extern void finish_header();
|
|
|
-void flush_archive();
|
|
|
-int isfile();
|
|
|
-int new_volume();
|
|
|
-void verify_volume();
|
|
|
extern void to_oct();
|
|
|
|
|
|
#ifndef __MSDOS__
|
|
@@ -125,10 +142,7 @@ static int r_error_count;
|
|
|
/*
|
|
|
* Have we hit EOF yet?
|
|
|
*/
|
|
|
-static int hit_eof;
|
|
|
-
|
|
|
-/* Checkpointing counter */
|
|
|
-static int checkpoint;
|
|
|
+static int eof;
|
|
|
|
|
|
/* JF we're reading, but we just read the last record and its time to update */
|
|
|
extern time_to_start_writing;
|
|
@@ -137,7 +151,6 @@ int file_to_switch_to= -1; /* If remote update, close archive, and use
|
|
|
|
|
|
static int volno = 1; /* JF which volume of a multi-volume tape
|
|
|
we're on */
|
|
|
-static int global_volno = 1; /* Volume number to print in external messages. */
|
|
|
|
|
|
char *save_name = 0; /* Name of the file we are currently writing */
|
|
|
long save_totsize; /* total size of file we are writing. Only
|
|
@@ -157,8 +170,8 @@ static long real_s_sizeleft;
|
|
|
void
|
|
|
reset_eof()
|
|
|
{
|
|
|
- if(hit_eof) {
|
|
|
- hit_eof=0;
|
|
|
+ if(eof) {
|
|
|
+ eof=0;
|
|
|
ar_record=ar_block;
|
|
|
ar_last=ar_block+blocking;
|
|
|
ar_reading=0;
|
|
@@ -174,11 +187,11 @@ union record *
|
|
|
findrec()
|
|
|
{
|
|
|
if (ar_record == ar_last) {
|
|
|
- if (hit_eof)
|
|
|
+ if (eof)
|
|
|
return (union record *)NULL; /* EOF */
|
|
|
flush_archive();
|
|
|
if (ar_record == ar_last) {
|
|
|
- hit_eof++;
|
|
|
+ eof++;
|
|
|
return (union record *)NULL; /* EOF */
|
|
|
}
|
|
|
}
|
|
@@ -245,11 +258,11 @@ dupto(from, to, msg)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#ifdef __MSDOS__
|
|
|
+#ifdef MSDOS
|
|
|
void
|
|
|
child_open()
|
|
|
{
|
|
|
- fprintf(stderr,"MS-DOS %s can't use compressed or remote archives\n",tar);
|
|
|
+ fprintf(stderr,"MSDOS %s can't use compressed or remote archives\n",tar);
|
|
|
exit(EX_ARGSBAD);
|
|
|
}
|
|
|
#else
|
|
@@ -461,7 +474,6 @@ child_open()
|
|
|
|
|
|
|
|
|
/* return non-zero if p is the name of a directory */
|
|
|
-int
|
|
|
isfile(p)
|
|
|
char *p;
|
|
|
{
|
|
@@ -469,7 +481,7 @@ char *p;
|
|
|
|
|
|
if(stat(p,&stbuf)<0)
|
|
|
return 1;
|
|
|
- if(S_ISREG(stbuf.st_mode))
|
|
|
+ if((stbuf.st_mode&S_IFMT)==S_IFREG)
|
|
|
return 1;
|
|
|
return 0;
|
|
|
}
|
|
@@ -481,7 +493,6 @@ char *p;
|
|
|
* reading or writing.
|
|
|
*/
|
|
|
/* JF if the arg is 2, open for reading and writing. */
|
|
|
-void
|
|
|
open_archive(reading)
|
|
|
int reading;
|
|
|
{
|
|
@@ -546,23 +557,23 @@ open_archive(reading)
|
|
|
} else {
|
|
|
archive = rmtcreat(ar_file, 0666);
|
|
|
}
|
|
|
- if (archive < 0) {
|
|
|
- msg_perror("can't open %s",ar_file);
|
|
|
- exit(EX_BADARCH);
|
|
|
- }
|
|
|
#ifndef __MSDOS__
|
|
|
if(!_isrmt(archive)) {
|
|
|
struct stat tmp_stat;
|
|
|
|
|
|
fstat(archive,&tmp_stat);
|
|
|
- if(S_ISREG(tmp_stat.st_mode)) {
|
|
|
+ if((tmp_stat.st_mode&S_IFMT)==S_IFREG) {
|
|
|
ar_dev=tmp_stat.st_dev;
|
|
|
ar_ino=tmp_stat.st_ino;
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-#ifdef __MSDOS__
|
|
|
+ if (archive < 0) {
|
|
|
+ msg_perror("can't open %s",ar_file);
|
|
|
+ exit(EX_BADARCH);
|
|
|
+ }
|
|
|
+#ifdef MSDOS
|
|
|
setmode(archive, O_BINARY);
|
|
|
#endif
|
|
|
|
|
@@ -625,7 +636,6 @@ open_archive(reading)
|
|
|
* adding (baserec+ar_record), doing a 9-bit shift of baserec, then
|
|
|
* subtracting ar_block from that, shifting it back, losing the top 9 bits.
|
|
|
*/
|
|
|
-void
|
|
|
saverec(pointer)
|
|
|
union record **pointer;
|
|
|
{
|
|
@@ -647,15 +657,12 @@ saverec(pointer)
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
-void
|
|
|
fl_write()
|
|
|
{
|
|
|
int err;
|
|
|
int copy_back;
|
|
|
static long bytes_written = 0;
|
|
|
|
|
|
- if (f_checkpoint && ! (++checkpoint % 10))
|
|
|
- msg ("Write checkpoint %d\n", checkpoint);
|
|
|
if(tape_length && bytes_written >= tape_length * 1024) {
|
|
|
errno = ENOSPC;
|
|
|
err = 0;
|
|
@@ -676,7 +683,7 @@ fl_write()
|
|
|
real_s_sizeleft = 0;
|
|
|
return;
|
|
|
}
|
|
|
-#ifdef __MSDOS__
|
|
|
+#ifdef MSDOS
|
|
|
if(save_name[1]==':')
|
|
|
save_name+=2;
|
|
|
#endif
|
|
@@ -692,11 +699,9 @@ fl_write()
|
|
|
|
|
|
/* We're multivol Panic if we didn't get the right kind of response */
|
|
|
/* ENXIO is for the UNIX PC */
|
|
|
- if(err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO)
|
|
|
+ if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO))
|
|
|
writeerror(err);
|
|
|
|
|
|
- /* If error indicates a short write, we just move to the next tape. */
|
|
|
-
|
|
|
if(new_volume(0)<0)
|
|
|
return;
|
|
|
bytes_written=0;
|
|
@@ -755,7 +760,7 @@ fl_write()
|
|
|
else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back)
|
|
|
real_s_name[0] = '\0';
|
|
|
else {
|
|
|
-#ifdef __MSDOS__
|
|
|
+#ifdef MSDOS
|
|
|
if(save_name[1]==':')
|
|
|
save_name+=2;
|
|
|
#endif
|
|
@@ -822,16 +827,12 @@ readerror()
|
|
|
/*
|
|
|
* Perform a read to flush the buffer.
|
|
|
*/
|
|
|
-void
|
|
|
fl_read()
|
|
|
{
|
|
|
int err; /* Result from system call */
|
|
|
int left; /* Bytes left */
|
|
|
char *more; /* Pointer to next byte to read */
|
|
|
|
|
|
- if (f_checkpoint && ! (++checkpoint % 10))
|
|
|
- msg ("Read checkpoint %d\n", checkpoint);
|
|
|
-
|
|
|
/*
|
|
|
* Clear the count of errors. This only applies to a single
|
|
|
* call to fl_read. We leave read_error_flag alone; it is
|
|
@@ -858,7 +859,7 @@ fl_read()
|
|
|
if(f_multivol) {
|
|
|
if(save_name) {
|
|
|
if(save_name!=real_s_name) {
|
|
|
-#ifdef __MSDOS__
|
|
|
+#ifdef MSDOS
|
|
|
if(save_name[1]==':')
|
|
|
save_name+=2;
|
|
|
#endif
|
|
@@ -883,7 +884,7 @@ error_loop:
|
|
|
if (err == blocksize)
|
|
|
return;
|
|
|
|
|
|
- if((err == 0 || (err<0 && errno==ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) {
|
|
|
+ if((err == 0 || (err<0 && errno==ENOSPC)) && f_multivol) {
|
|
|
union record *head;
|
|
|
|
|
|
try_volume:
|
|
@@ -914,7 +915,6 @@ error_loop:
|
|
|
msg("Volume mismatch! %s!=%s",f_volhdr,
|
|
|
head->header.name);
|
|
|
--volno;
|
|
|
- --global_volno;
|
|
|
goto try_volume;
|
|
|
}
|
|
|
|
|
@@ -922,7 +922,6 @@ error_loop:
|
|
|
if(strcmp(ptr,head->header.name)) {
|
|
|
msg("Volume mismatch! %s!=%s",ptr,head->header.name);
|
|
|
--volno;
|
|
|
- --global_volno;
|
|
|
free(ptr);
|
|
|
goto try_volume;
|
|
|
}
|
|
@@ -942,7 +941,6 @@ error_loop:
|
|
|
if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) {
|
|
|
msg("%s is not continued on this volume!",real_s_name);
|
|
|
--volno;
|
|
|
- --global_volno;
|
|
|
goto try_volume;
|
|
|
}
|
|
|
if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) {
|
|
@@ -951,13 +949,11 @@ error_loop:
|
|
|
from_oct(1+12,head->header.size),
|
|
|
from_oct(1+12,head->header.offset));
|
|
|
--volno;
|
|
|
- --global_volno;
|
|
|
goto try_volume;
|
|
|
}
|
|
|
if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) {
|
|
|
msg("This volume is out of sequence");
|
|
|
--volno;
|
|
|
- --global_volno;
|
|
|
goto try_volume;
|
|
|
}
|
|
|
head++;
|
|
@@ -1014,7 +1010,6 @@ error2loop:
|
|
|
/*
|
|
|
* Flush the current buffer to/from the archive.
|
|
|
*/
|
|
|
-void
|
|
|
flush_archive()
|
|
|
{
|
|
|
int c;
|
|
@@ -1046,7 +1041,6 @@ flush_archive()
|
|
|
/* Backspace the archive descriptor by one blocks worth.
|
|
|
If its a tape, MTIOCTOP will work. If its something else,
|
|
|
we try to seek on it. If we can't seek, we lose! */
|
|
|
-int
|
|
|
backspace_output()
|
|
|
{
|
|
|
long cur;
|
|
@@ -1084,7 +1078,6 @@ backspace_output()
|
|
|
/*
|
|
|
* Close the archive file.
|
|
|
*/
|
|
|
-void
|
|
|
close_archive()
|
|
|
{
|
|
|
int child;
|
|
@@ -1094,11 +1087,12 @@ close_archive()
|
|
|
if (time_to_start_writing || !ar_reading)
|
|
|
flush_archive();
|
|
|
if(cmd_mode==CMD_DELETE) {
|
|
|
- off_t pos;
|
|
|
+ long pos;
|
|
|
|
|
|
pos = rmtlseek(archive,0L,1);
|
|
|
-#ifndef __MSDOS__
|
|
|
- (void) ftruncate(archive,pos);
|
|
|
+#ifndef MSDOS
|
|
|
+ /* FIXME does ftruncate really take an INT?! */
|
|
|
+ (void) ftruncate(archive,(int)pos);
|
|
|
#else
|
|
|
(void)rmtwrite(archive,"",0);
|
|
|
#endif
|
|
@@ -1109,7 +1103,7 @@ close_archive()
|
|
|
if((c=rmtclose(archive))<0)
|
|
|
msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
|
|
|
|
|
|
-#ifndef __MSDOS__
|
|
|
+#ifndef MSDOS
|
|
|
if (childpid) {
|
|
|
/*
|
|
|
* Loop waiting for the right child to die, or for
|
|
@@ -1119,32 +1113,32 @@ close_archive()
|
|
|
;
|
|
|
|
|
|
if (child != -1) {
|
|
|
- switch (WTERMSIG(status)) {
|
|
|
+ switch (TERM_SIGNAL(status)) {
|
|
|
case 0:
|
|
|
/* Child voluntarily terminated -- but why? */
|
|
|
- if (WEXITSTATUS(status) == MAGIC_STAT) {
|
|
|
+ if (TERM_VALUE(status) == MAGIC_STAT) {
|
|
|
exit(EX_SYSTEM);/* Child had trouble */
|
|
|
}
|
|
|
- if (WEXITSTATUS(status) == (SIGPIPE + 128)) {
|
|
|
+ if (TERM_VALUE(status) == (SIGPIPE + 128)) {
|
|
|
/*
|
|
|
* /bin/sh returns this if its child
|
|
|
* dies with SIGPIPE. 'Sok.
|
|
|
*/
|
|
|
break;
|
|
|
- } else if (WEXITSTATUS(status))
|
|
|
+ } else if (TERM_VALUE(status))
|
|
|
msg("child returned status %d",
|
|
|
- WEXITSTATUS(status));
|
|
|
+ TERM_VALUE(status));
|
|
|
case SIGPIPE:
|
|
|
break; /* This is OK. */
|
|
|
|
|
|
default:
|
|
|
msg("child died with signal %d%s",
|
|
|
- WTERMSIG(status),
|
|
|
- WIFCOREDUMPED(status)? " (core dumped)": "");
|
|
|
+ TERM_SIGNAL(status),
|
|
|
+ TERM_COREDUMP(status)? " (core dumped)": "");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-#endif /* __MSDOS__ */
|
|
|
+#endif /* MSDOS */
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1203,42 +1197,8 @@ anno(stream, prefix, savedp)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-/* Called to initialize the global volume number. */
|
|
|
-int
|
|
|
-init_volume_number ()
|
|
|
-{
|
|
|
- FILE *vf;
|
|
|
-
|
|
|
- vf = fopen (f_volno_file, "r");
|
|
|
- if (!vf && errno != ENOENT)
|
|
|
- msg_perror ("%s", f_volno_file);
|
|
|
-
|
|
|
- if (vf)
|
|
|
- {
|
|
|
- fscanf (vf, "%d", &global_volno);
|
|
|
- fclose (vf);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/* Called to write out the closing global volume number. */
|
|
|
-int
|
|
|
-closeout_volume_number ()
|
|
|
-{
|
|
|
- FILE *vf;
|
|
|
-
|
|
|
- vf = fopen (f_volno_file, "w");
|
|
|
- if (!vf)
|
|
|
- msg_perror ("%s", f_volno_file);
|
|
|
- else
|
|
|
- {
|
|
|
- fprintf (vf, "%d\n", global_volno);
|
|
|
- fclose (vf);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/* We've hit the end of the old volume. Close it and open the next one */
|
|
|
/* Values for type: 0: writing 1: reading 2: updating */
|
|
|
-int
|
|
|
new_volume(type)
|
|
|
int type;
|
|
|
{
|
|
@@ -1260,13 +1220,12 @@ int type;
|
|
|
if((c=rmtclose(archive))<0)
|
|
|
msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
|
|
|
|
|
|
- global_volno++;
|
|
|
volno++;
|
|
|
tryagain:
|
|
|
if (f_run_script_at_end)
|
|
|
system(info_script);
|
|
|
else for(;;) {
|
|
|
- fprintf(msg_file,"\007Prepare volume #%d and hit return: ",global_volno);
|
|
|
+ fprintf(msg_file,"\007Prepare volume #%d and hit return: ",volno);
|
|
|
fflush(msg_file);
|
|
|
if(fgets(inbuf,sizeof(inbuf),read_file)==0) {
|
|
|
fprintf(msg_file,"EOF? What does that mean?");
|
|
@@ -1317,7 +1276,7 @@ int type;
|
|
|
break;
|
|
|
|
|
|
case '!':
|
|
|
-#ifdef __MSDOS__
|
|
|
+#ifdef MSDOS
|
|
|
spawnl(P_WAIT,getenv("COMSPEC"),"-",0);
|
|
|
#else
|
|
|
/* JF this needs work! */
|
|
@@ -1353,7 +1312,7 @@ int type;
|
|
|
msg_perror("can't open %s",ar_file);
|
|
|
goto tryagain;
|
|
|
}
|
|
|
-#ifdef __MSDOS__
|
|
|
+#ifdef MSDOS
|
|
|
setmode(archive,O_BINARY);
|
|
|
#endif
|
|
|
return 0;
|