/* util.c - Several utility routines for cpio.
Copyright (C) 1990-1992, 2001, 2004, 2006-2007, 2010-2011, 2014 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#include <system.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "cpiohdr.h"
#include "dstring.h"
#include "extern.h"
#include <paxlib.h>
#include "filetypes.h"
#include <safe-read.h>
#include <full-write.h>
#include <rmt.h>
#include <hash.h>
#include <utimens.h>
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_MTIO_H
# ifdef HAVE_SYS_IO_TRIOCTL_H
# include <sys/io/trioctl.h>
# endif
# include <sys/mtio.h>
#endif
#if !HAVE_DECL_ERRNO
extern int errno;
#endif
/* Write `output_size' bytes of `output_buffer' to file
descriptor OUT_DES and reset `output_size' and `out_buff'. */
void
tape_empty_output_buffer (int out_des)
{
int bytes_written;
#ifdef BROKEN_LONG_TAPE_DRIVER
static long output_bytes_before_lseek = 0;
/* Some tape drivers seem to have a signed internal seek pointer and
they lose if it overflows and becomes negative (e.g. when writing
tapes > 2Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
seek pointer and prevent it from overflowing. */
if (output_is_special
&& ( (output_bytes_before_lseek += output_size) >= 1073741824L) )
{
lseek(out_des, 0L, SEEK_SET);
output_bytes_before_lseek = 0;
}
#endif
bytes_written = rmtwrite (out_des, output_buffer, output_size);
if (bytes_written != output_size)
{
int rest_bytes_written;
int rest_output_size;
if (output_is_special
&& (bytes_written >= 0
|| (bytes_written < 0
&& (errno == ENOSPC || errno == EIO || errno == ENXIO))))
{
get_next_reel (out_des);
if (bytes_written > 0)
rest_output_size = output_size - bytes_written;
else
rest_output_size = output_size;
rest_bytes_written = rmtwrite (out_des, output_buffer,
rest_output_size);
if (rest_bytes_written != rest_output_size)
error (PAXEXIT_FAILURE, errno, _("write error"));
}
else
error (PAXEXIT_FAILURE, errno, _("write error"));
}
output_bytes += output_size;
out_buff = output_buffer;
output_size = 0;
}
static ssize_t sparse_write (int fildes, char *buf, size_t nbyte, bool flush);
/* Write `output_size' bytes of `output_buffer' to file
descriptor OUT_DES and reset `output_size' and `out
|