📄 buffer.c
字号:
}
err=rmtwrite(archive, ar_block->charptr, (int)blocksize);
if(err!=blocksize)
writeerror(err);
}
}
/* close_archive(); */
exit(0);
}
}
/* So we should exec compress (-d) */
if(ar_reading)
execlp("compress", "compress", "-d", (char *)0);
else
execlp("compress", "compress", (char *)0);
msg_perror("can't exec compress");
_exit(EX_SYSTEM);
}
/* return non-zero if p is the name of a directory */
isfile(p)
char *p;
{
struct stat stbuf;
if(stat(p,&stbuf)<0)
return 1;
if((stbuf.st_mode&S_IFMT)==S_IFREG)
return 1;
return 0;
}
#endif
/*
* Open an archive file. The argument specifies whether we are
* reading or writing.
*/
/* JF if the arg is 2, open for reading and writing. */
open_archive(reading)
int reading;
{
msg_file = f_exstdout ? stderr : stdout;
if (blocksize == 0) {
msg("invalid value for blocksize");
exit(EX_ARGSBAD);
}
if(ar_file==0) {
msg("No archive name given, what should I do?");
exit(EX_BADARCH);
}
/*NOSTRICT*/
if(f_multivol) {
ar_block = (union record *) valloc((unsigned)(blocksize+(2*RECORDSIZE)));
if(ar_block)
ar_block += 2;
} else
ar_block = (union record *) valloc((unsigned)blocksize);
if (!ar_block) {
msg("could not allocate memory for blocking factor %d",
blocking);
exit(EX_ARGSBAD);
}
ar_record = ar_block;
ar_last = ar_block + blocking;
ar_reading = reading;
if (f_compress) {
if(reading==2 || f_verify) {
msg("cannot update or verify compressed archives");
exit(EX_ARGSBAD);
}
child_open();
if(!reading && ar_file[0]=='-' && ar_file[1]=='\0')
msg_file = stderr;
/* child_open(rem_host, rem_file); */
} else if (ar_file[0] == '-' && ar_file[1] == '\0') {
f_reblock++; /* Could be a pipe, be safe */
if(f_verify) {
msg("can't verify stdin/stdout archive");
exit(EX_ARGSBAD);
}
if(reading==2) {
archive=STDIN;
msg_file=stderr;
write_archive_to_stdout++;
} else if (reading)
archive = STDIN;
else {
archive = STDOUT;
msg_file = stderr;
}
} else if (reading==2 || f_verify) {
archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
} else if(reading) {
archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666);
} else {
archive = rmtcreat(ar_file, 0666);
}
#ifndef __MSDOS__
if(!_isrmt(archive)) {
struct stat tmp_stat;
fstat(archive,&tmp_stat);
if((tmp_stat.st_mode&S_IFMT)==S_IFREG) {
ar_dev=tmp_stat.st_dev;
ar_ino=tmp_stat.st_ino;
}
}
#endif
if (archive < 0) {
msg_perror("can't open %s",ar_file);
exit(EX_BADARCH);
}
#ifdef MSDOS
setmode(archive, O_BINARY);
#endif
if (reading) {
ar_last = ar_block; /* Set up for 1st block = # 0 */
(void) findrec(); /* Read it in, check for EOF */
if(f_volhdr) {
union record *head;
#if 0
char *ptr;
if(f_multivol) {
ptr=malloc(strlen(f_volhdr)+20);
sprintf(ptr,"%s Volume %d",f_volhdr,1);
} else
ptr=f_volhdr;
#endif
head=findrec();
if(!head) {
msg("Archive not labelled to match %s",f_volhdr);
exit(EX_BADVOL);
}
if (re_match (label_pattern, head->header.name,
strlen (head->header.name), 0, 0) < 0) {
msg ("Volume mismatch! %s!=%s", f_volhdr,
head->header.name);
exit (EX_BADVOL);
}
#if 0
if(strcmp(ptr,head->header.name)) {
msg("Volume mismatch! %s!=%s",ptr,head->header.name);
exit(EX_BADVOL);
}
if(ptr!=f_volhdr)
free(ptr);
#endif
}
} else if(f_volhdr) {
bzero((void *)ar_block,RECORDSIZE);
if(f_multivol)
sprintf(ar_block->header.name,"%s Volume 1",f_volhdr);
else
strcpy(ar_block->header.name,f_volhdr);
ar_block->header.linkflag = LF_VOLHDR;
to_oct(time(0), 1+12, ar_block->header.mtime);
finish_header(ar_block);
/* ar_record++; */
}
}
/*
* Remember a union record * as pointing to something that we
* need to keep when reading onward in the file. Only one such
* thing can be remembered at once, and it only works when reading
* an archive.
*
* We calculate "offset" then add it because some compilers end up
* 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.
*/
saverec(pointer)
union record **pointer;
{
long offset;
save_rec = pointer;
offset = ar_record - ar_block;
saved_recno = baserec + offset;
}
/*
* Perform a write to flush the buffer.
*/
/*send_buffer_to_file();
if(new_volume) {
deal_with_new_volume_stuff();
send_buffer_to_file();
}
*/
fl_write()
{
int err;
int copy_back;
static long bytes_written = 0;
if(tape_length && bytes_written >= tape_length * 1024) {
errno = ENOSPC;
err = 0;
} else
err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
if(err!=blocksize && !f_multivol)
writeerror(err);
else if (f_totals)
tot_written += blocksize;
if(err>0)
bytes_written+=err;
if (err == blocksize) {
if(f_multivol) {
if(!save_name) {
real_s_name[0]='\0';
real_s_totsize=0;
real_s_sizeleft = 0;
return;
}
#ifdef MSDOS
if(save_name[1]==':')
save_name+=2;
#endif
while(*save_name=='/')
save_name++;
strcpy(real_s_name,save_name);
real_s_totsize = save_totsize;
real_s_sizeleft = save_sizeleft;
}
return;
}
/* We're multivol Panic if we didn't get the right kind of response */
/* ENXIO is for the UNIX PC */
if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO))
writeerror(err);
if(new_volume(0)<0)
return;
bytes_written=0;
if(f_volhdr && real_s_name[0]) {
copy_back=2;
ar_block-=2;
} else if(f_volhdr || real_s_name[0]) {
copy_back = 1;
ar_block--;
} else
copy_back = 0;
if(f_volhdr) {
bzero((void *)ar_block,RECORDSIZE);
sprintf(ar_block->header.name,"%s Volume %d",f_volhdr,volno);
to_oct(time(0), 1+12, ar_block->header.mtime);
ar_block->header.linkflag = LF_VOLHDR;
finish_header(ar_block);
}
if(real_s_name[0]) {
int tmp;
if(f_volhdr)
ar_block++;
bzero((void *)ar_block,RECORDSIZE);
strcpy(ar_block->header.name,real_s_name);
ar_block->header.linkflag = LF_MULTIVOL;
to_oct((long)real_s_sizeleft,1+12,
ar_block->header.size);
to_oct((long)real_s_totsize-real_s_sizeleft,
1+12,ar_block->header.offset);
tmp=f_verbose;
f_verbose=0;
finish_header(ar_block);
f_verbose=tmp;
if(f_volhdr)
ar_block--;
}
err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
if(err!=blocksize)
writeerror(err);
else if (f_totals)
tot_written += blocksize;
bytes_written = blocksize;
if(copy_back) {
ar_block+=copy_back;
bcopy((void *)(ar_block+blocking-copy_back),
(void *)ar_record,
copy_back*RECORDSIZE);
ar_record+=copy_back;
if(real_s_sizeleft>=copy_back*RECORDSIZE)
real_s_sizeleft-=copy_back*RECORDSIZE;
else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back)
real_s_name[0] = '\0';
else {
#ifdef MSDOS
if(save_name[1]==':')
save_name+=2;
#endif
while(*save_name=='/')
save_name++;
strcpy(real_s_name,save_name);
real_s_sizeleft = save_sizeleft;
real_s_totsize=save_totsize;
}
copy_back = 0;
}
}
/* Handle write errors on the archive. Write errors are always fatal */
/* Hitting the end of a volume does not cause a write error unless the write
* was the first block of the volume */
void
writeerror(err)
int err;
{
if (err < 0) {
msg_perror("can't write to %s",ar_file);
exit(EX_BADARCH);
} else {
msg("only wrote %u of %u bytes to %s",err,blocksize,ar_file);
exit(EX_BADARCH);
}
}
/*
* Handle read errors on the archive.
*
* If the read should be retried, readerror() returns to the caller.
*/
void
readerror()
{
# define READ_ERROR_MAX 10
read_error_flag++; /* Tell callers */
msg_perror("read error on %s",ar_file);
if (baserec == 0) {
/* First block of tape. Probably stupidity error */
exit(EX_BADARCH);
}
/*
* Read error in mid archive. We retry up to READ_ERROR_MAX times
* and then give up on reading the archive. We set read_error_flag
* for our callers, so they can cope if they want.
*/
if (r_error_count++ > READ_ERROR_MAX) {
msg("Too many errors, quitting.");
exit(EX_BADARCH);
}
return;
}
/*
* Perform a read to flush the buffer.
*/
fl_read()
{
int err; /* Result from system call */
int left; /* Bytes left */
char *more; /* Pointer to next byte to read */
/*
* Clear the count of errors. This only applies to a single
* call to fl_read. We leave read_error_flag alone; it is
* only turned off by higher level software.
*/
r_error_count = 0; /* Clear error count */
/*
* If we are about to wipe out a record that
* somebody needs to keep, copy it out to a holding
* area and adjust somebody's pointer to it.
*/
if (save_rec &&
*save_rec >= ar_record &&
*save_rec < ar_last) {
record_save_area = **save_rec;
*save_rec = &record_save_area;
}
if(write_archive_to_stdout && baserec!=0) {
err=rmtwrite(1, ar_block->charptr, blocksize);
if(err!=blocksize)
writeerror(err);
}
if(f_multivol) {
if(save_name) {
if(save_name!=real_s_name) {
#ifdef MSDOS
if(save_name[1]==':')
save_name+=2;
#endif
while(*save_name=='/')
save_name++;
strcpy(real_s_name,save_name);
save_name=real_s_name;
}
real_s_totsize = save_totsize;
real_s_sizeleft = save_sizeleft;
} else {
real_s_name[0]='\0';
real_s_totsize=0;
real_s_sizeleft = 0;
}
}
error_loop:
err = rmtread(archive, ar_block->charptr, (int)blocksize);
if (err == blocksize)
return;
if((err == 0 || (err<0 && errno==ENOSPC)) && f_multivol) {
union record *head;
try_volume:
if(new_volume((cmd_mode==CMD_APPEND || cmd_mode==CMD_CAT || cmd_mode==CMD_UPDATE) ? 2 : 1)<0)
return;
vol_error:
err = rmtread(archive, ar_block->charptr,(int) blocksize);
if(err < 0) {
readerror();
goto vol_error;
}
if(err!=blocksize)
goto short_read;
head=ar_block;
if(head->header.linkflag==LF_VOLHDR) {
if(f_volhdr) {
#if 0
char *ptr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -