⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buffer.c

📁 unix 下tar 执行程序的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
					}
					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 + -