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

📄 buffer.c

📁 speech signal process tools
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Buffer management for tar.   Copyright (C) 1988 Free Software FoundationThis file is part of GNU Tar.GNU Tar is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU Tar is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Tar; see the file COPYING.  If not, write tothe 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>#include <sys/types.h>		/* For non-Berkeley systems */#include <sys/stat.h>#include <signal.h>#ifndef MSDOS#include <sys/ioctl.h>#if !defined(USG) || defined(HAVE_MTIO)#include <sys/mtio.h>#endif#endif#ifdef	MSDOS# include <fcntl.h>#include <process.h>#else# ifdef XENIX#  include <sys/inode.h># endif# include <sys/file.h>#endifextern int errno;#include "tar.h"#include "port.h"#include "rmt.h"/* Either stdout or stderr:  The thing we write messages (standard msgs, not   errors) to.  Stdout unless we're writing a pipe, in which case stderr */FILE *msg_file = stdout;#define	STDIN	0		/* Standard input  file descriptor */#define	STDOUT	1		/* Standard output file descriptor */#define	PREAD	0		/* Read  file descriptor from pipe() */#define	PWRITE	1		/* Write file descriptor from pipe() */#ifdef __STDC__extern void	*malloc();extern void	*valloc();#elseextern char	*malloc();extern char	*valloc();#endifextern 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! */void writeerror();void readerror();void ck_pipe();void ck_close();extern void finish_header();extern void to_oct();/* Obnoxious test to see if dimwit is trying to dump the archive */dev_t ar_dev;ino_t ar_ino;/* * The record pointed to by save_rec should not be overlaid * when reading in a new tape block.  Copy it to record_save_area first, and * change the pointer in *save_rec to point to record_save_area. * Saved_recno records the record number at the time of the save. * This is used by annofile() to print the record number of a file's * header record. */static union record **save_rec; union record record_save_area;static long	    saved_recno;/* * PID of child program, if f_compress or remote archive access. */static int	childpid = 0;/* * Record number of the start of this block of records */long	baserec;/* * Error recovery stuff */static int	r_error_count;/* * Have we hit EOF yet? */static int	eof;/* JF we're reading, but we just read the last record and its time to update */extern time_to_start_writing;int file_to_switch_to= -1;	/* If remote update, close archive, and use				   this descriptor to write to */static int volno = 1;		/* JF which volume of a multi-volume tape				   we're on */char *save_name = 0;		/* Name of the file we are currently writing */long save_totsize;		/* total size of file we are writing.  Only				   valid if save_name is non_zero */long save_sizeleft;		/* Where we are in the file we are writing.				   Only valid if save_name is non-zero */int write_archive_to_stdout;/* Used by fl_read and fl_write to store the real info about saved names */static char real_s_name[NAMSIZ];static long real_s_totsize;static long real_s_sizeleft;/* Reset the EOF flag (if set), and re-set ar_record, etc */voidreset_eof(){	if(eof) {		eof=0;		ar_record=ar_block;		ar_last=ar_block+blocking;		ar_reading=0;	}}/* * Return the location of the next available input or output record. * Return NULL for EOF.  Once we have returned NULL, we just keep returning * it, to avoid accidentally going on to the next file on the "tape". */union record *findrec(){	if (ar_record == ar_last) {		if (eof)			return (union record *)NULL;	/* EOF */		flush_archive();		if (ar_record == ar_last) {			eof++;			return (union record *)NULL;	/* EOF */		}	}	return ar_record;}/* * Indicate that we have used all records up thru the argument. * (should the arg have an off-by-1? XXX FIXME) */voiduserec(rec)	union record *rec;{	while(rec >= ar_record)		ar_record++;	/*	 * Do NOT flush the archive here.  If we do, the same	 * argument to userec() could mean the next record (if the	 * input block is exactly one record long), which is not what	 * is intended.	 */	if (ar_record > ar_last)		abort();}/* * Return a pointer to the end of the current records buffer. * All the space between findrec() and endofrecs() is available * for filling with data, or taking data from. */union record *endofrecs(){	return ar_last;}/* * Duplicate a file descriptor into a certain slot. * Equivalent to BSD "dup2" with error reporting. */voiddupto(from, to, msg)	int from, to;	char *msg;{	int err;	if (from != to) {		err=close(to);		if(err<0 && errno!=EBADF) {			msg_perror("Cannot close descriptor %d",to);			exit(EX_SYSTEM);		}		err = dup(from);		if (err != to) {			msg_perror("cannot dup %s",msg);			exit(EX_SYSTEM);		}		ck_close(from);	}}#ifdef MSDOSvoidchild_open(){	fprintf(stderr,"MSDOS %s can't use compressed or remote archives\n",tar);	exit(EX_ARGSBAD);}#elsevoidchild_open(){	int pipe[2];	int err = 0;	int kidpipe[2];	int kidchildpid;#define READ	0#define WRITE	1	ck_pipe(pipe);	childpid=fork();	if(childpid<0) {		msg_perror("cannot fork");		exit(EX_SYSTEM);	}	if(childpid>0) {		/* We're the parent.  Clean up and be happy */		/* This, at least, is easy */		if(ar_reading) {			f_reblock++;			archive=pipe[READ];			ck_close(pipe[WRITE]);		} else {			archive = pipe[WRITE];			ck_close(pipe[READ]);		}		return;	}	/* We're the kid */	if(ar_reading) {		dupto(pipe[WRITE],STDOUT,"(child) pipe to stdout");		ck_close(pipe[READ]);	} else {		dupto(pipe[READ],STDIN,"(child) pipe to stdin");		ck_close(pipe[WRITE]);	}	/* We need a child tar only if	   1: we're reading/writing stdin/out (to force reblocking)	   2: the file is to be accessed by rmt (compress doesn't know how)	   3: the file is not a plain file */#ifdef NO_REMOTE	if(!(ar_file[0]=='-' && ar_file[1]=='\0') && isfile(ar_file))#else	if(!(ar_file[0]=='-' && ar_file[1]=='\0') && !_remdev(ar_file) && isfile(ar_file))#endif	{		/* We don't need a child tar.  Open the archive */		if(ar_reading) {			archive=open(ar_file, O_RDONLY|O_BINARY, 0666);			if(archive<0) {				msg_perror("can't open archive %s",ar_file);				exit(EX_BADARCH);			}			dupto(archive,STDIN,"archive to stdin");			/* close(archive); */		} else {			archive=creat(ar_file,0666);			if(archive<0) {				msg_perror("can't open archive %s",ar_file);				exit(EX_BADARCH);			}			dupto(archive,STDOUT,"archive to stdout");			/* close(archive); */		}	} else {		/* We need a child tar */		ck_pipe(kidpipe);		kidchildpid=fork();		if(kidchildpid<0) {			msg_perror("child can't fork");			exit(EX_SYSTEM);		}		if(kidchildpid>0) {			/* About to exec compress:  set up the files */			if(ar_reading) {				dupto(kidpipe[READ],STDIN,"((child)) pipe to stdin");				ck_close(kidpipe[WRITE]);				/* dup2(pipe[WRITE],STDOUT); */			} else {				/* dup2(pipe[READ],STDIN); */				dupto(kidpipe[WRITE],STDOUT,"((child)) pipe to stdout");				ck_close(kidpipe[READ]);			}			/* ck_close(pipe[READ]); */			/* ck_close(pipe[WRITE]); */			/* ck_close(kidpipe[READ]);			ck_close(kidpipe[WRITE]); */		} else {		/* Grandchild.  Do the right thing, namely sit here and		   read/write the archive, and feed stuff back to compress */			tar="tar (child)";			if(ar_reading) {				dupto(kidpipe[WRITE],STDOUT,"[child] pipe to stdout");				ck_close(kidpipe[READ]);			} else {				dupto(kidpipe[READ],STDIN,"[child] pipe to stdin");				ck_close(kidpipe[WRITE]);			}			if (ar_file[0] == '-' && ar_file[1] == '\0') {				if (ar_reading)					archive = STDIN;				else					archive = STDOUT;			} else /* This can't happen if (ar_reading==2)				archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);			else */if(ar_reading)				archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666);			else				archive = rmtcreat(ar_file, 0666);			if (archive < 0) {				msg_perror("can't open archive %s",ar_file);				exit(EX_BADARCH);			}			if(ar_reading) {				for(;;) {					char *ptr;					int max,count;							r_error_count = 0;				error_loop:					err=rmtread(archive, ar_block->charptr,(int)(blocksize));					if(err<0) {						readerror();						goto error_loop;					}					if(err==0)						break;					ptr = ar_block->charptr;					max = err;					while(max) {						count = (max<RECORDSIZE) ? max : RECORDSIZE;						err=write(STDOUT,ptr,count);						if(err!=count) {							if(err<0) {								msg_perror("can't write to compress");								exit(EX_SYSTEM);							} else								msg("write to compress short %d bytes",count-err);							count = (err<0) ? 0 : err;						}						ptr+=count;						max-=count;					}				}			} else {				for(;;) {					int n;					char *ptr;							n=blocksize;					ptr = ar_block->charptr;					while(n) {						err=read(STDIN,ptr,(n<RECORDSIZE) ? n : RECORDSIZE);						if(err<=0)							break;						n-=err;						ptr+=err;					}						/* EOF */					if(err==0) {						if(f_compress<2)							blocksize-=n;						else							bzero(ar_block->charptr+n,blocksize-n,n);						err=rmtwrite(archive,ar_block->charptr,blocksize);						if(err!=(blocksize))							writeerror(err);						if(f_compress<2)							blocksize+=n;						break;					}					if(n) {						msg_perror("can't read from compress");						exit(EX_SYSTEM);					}					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);	}	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;		}	}	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;			char *ptr;			if(f_multivol) {				ptr=malloc(strlen(f_volhdr)+20);				sprintf(ptr,"%s Volume %d",f_volhdr,1);			} else				ptr=f_volhdr;			head=findrec();			if(!head)				exit(EX_BADARCH);			if(strcmp(ptr,head->header.name)) {				msg("Volume mismatch!  %s!=%s\n",ptr,head->header.name);				exit(EX_BADARCH);			}			if(ptr!=f_volhdr)				free(ptr);		}	} 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;#ifdef TEST	static long test_written = 0;#endif#ifdef TEST	if(test_written>=30720) {		errno = ENOSPC;		err = 0;	} else#endif	err = rmtwrite(archive, ar_block->charptr,(int) blocksize);	if(err!=blocksize && !f_multivol)		writeerror(err);#ifdef TEST	if(err>0)		test_written+=err;#endif	if (err == blocksize) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -