buffer.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 647 行 · 第 1/2 页
C
647 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
/*
* Buffer management for public domain tar.
*
* Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
* MS-DOS port 2/87 by Eric Roskos.
* Minix port 3/88 by Eric Roskos.
*
* @(#) buffer.c 1.14 10/28/86 Public Domain - gnu
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h> /* For non-Berkeley systems */
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <process.h>
#include "tar.h"
#include "port.h"
#include "buffer.h"
#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() */
/*
* V7 doesn't have a #define for this.
*/
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#define MAGIC_STAT 105 /* Magic status returned by child, if it
* can't exec compress. We hope compress
* never returns this status! */
/*
* 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;
static union record record_save_area;
static int saved_recno;
#ifndef MSDOS
/*
* PID of child compress program, if f_compress.
*/
static int compress_pid;
#endif
/*
* Record number of the start of this block of records
*/
static int baserec;
/*
* Error recovery stuff
*/
static int r_error_count;
/*
* Return the location of the next available input or output record.
*/
union record *findrec( void )
{
if (ar_record == ar_last) {
flush_archive();
if (ar_record == ar_last)
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)
*/
void userec( 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( void )
{
return ar_last;
}
/*
* Open an archive file. The argument specifies whether we are
* reading or writing.
*
* With DOS, we ALWAYS open the archive in binary mode: whether or not
* to do CRLF translations depends on whether we open the input files
* as binary or ASCII, but we always write the archive without making
* any translations from what this program saw when it did the write.
*/
void open_archive( int read )
{
if (ar_file[0] == '-' && ar_file[1] == '\0')
{
if (read)
archive = STDIN;
else
archive = STDOUT;
}
else
if (read)
{
#if defined(MSDOS) && !defined(__NO_PHYS__)
archive = 9999; /* for debugging - invalid fd to cause err */
if (!f_phys) /* don't open if we're doing direct drive I/O */
#endif
archive = open(ar_file, O_RDONLY
#ifdef MSDOS
| O_BINARY
#endif
);
}
else
{
#if defined(MSDOS) && !defined(__NO_PHYS__)
archive = 9999;
if (!f_phys)
#endif
#ifdef V7
archive = creat(ar_file, 0666);
#else
archive = open(ar_file, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
0666);
#endif
}
if (archive < 0)
{
perror(ar_file);
exit(EX_BADARCH);
}
/* NOSTRICT */
ar_block = (union record *) valloc((unsigned) blocksize);
if (!ar_block)
{
fprintf(stderr,
"tar: could not allocate memory for blocking factor %d\n",
blocking);
exit(EX_ARGSBAD);
}
ar_record = ar_block;
ar_last = ar_block + blocking;
/*
* Handle compressed archives.
*
* FIXME, currently supported for reading only. FIXME, writing involves
* forking again for a small process that will reblock the output of
* compress to the user's specs.
*/
#ifndef MSDOS
if (f_compress)
{
int pipes[2];
int err;
if (!read)
{
fprintf(stderr,
"tar: cannot write compressed archives yet.\n");
exit(EX_ARGSBAD);
}
/* Create a pipe to get compress's output to us */
err = pipe(pipes);
if (err < 0)
{
perror("tar: cannot create pipe to compress");
exit(EX_SYSTEM);
}
/* Fork compress process */
compress_pid = fork();
if (compress_pid < 0)
{
perror("tar: cannot fork compress");
exit(EX_SYSTEM);
}
/*
* Child process.
*
* Move input to stdin, write side of pipe to stdout, then exec
* compress.
*/
if (compress_pid == 0)
{
(void) close(pipes[PREAD]); /* We won't use it */
if (archive != STDIN)
{
(void) close(STDIN);
err = dup(archive);
if (err != 0)
{
perror(
"tar: cannot dup input to stdin");
exit(EX_SYSTEM);
}
(void) close(archive);
}
if (pipes[PWRITE] != STDOUT)
{
(void) close(STDOUT);
err = dup(pipes[PWRITE]);
if (err != STDOUT)
{
perror(
"tar: cannot dup pipe output");
exit(MAGIC_STAT);
}
(void) close(pipes[PWRITE]);
}
#ifdef V7
execl("/usr/bin/compress", "compress", "-d", (char *)0);
#else
execlp("compress", "compress", "-d", (char *) 0);
#endif
perror("tar: cannot exec compress");
exit(MAGIC_STAT);
}
/*
* Parent process. Clean up. FIXME, note that this may leave
* standard input closed, if the compressed archive was on standard
* input.
*/
(void) close(archive); /* Close compressed archive */
(void) close(pipes[PWRITE]); /* Close write side of pipe */
archive = pipes[PREAD]; /* Read side is our archive */
#ifdef BSD42
f_reblock++; /* Pipe will give random # of bytes */
#endif /* BSD42 */
}
#endif /* MSDOS */
ar_reading = read;
if (read)
{
ar_last = ar_block; /* Set up for 1st block = # 0 */
flush_archive();
}
}
/*
* 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.
*/
void saverec(union record **pointer)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?