/*
 * nqs_generic/all-systems/filecopy.c
 * Routine to copy an entire file from one stream to another
 */

#include <nqs_generic/license.h>
  /* NQS license information */
#include <nqs_generic/debug.h>
  /* debugging support */
#include <nqs_generic/proto.h>
  /* ANSI C prototypes */
#include <errno.h>
  /* System call error number value */
#include <unistd.h>
  /* for file i/o operations */

/*** filecopyentire
 *
 *	int filecopyentire():
 *	Copy a file from one open file descriptor to another.
 *	Don't stop until EOF.
 *
 *	Returns:
 *	      >=0: if successful (number of bytes transferred);
 *	       -1: if an error occurs (in which case errno is set).
 *		   Errno will equal zero, if we simply ran out of
 *		   file space writing the copy.
 */

long filecopyentire (int iFrom, int iTo)
{
  char szBuffer [8192];
    /* Copy buffer */
  register int  iRead;
    /* One time number of bytes read */
  register int  iWritten;
    /* One time number of bytes written */
  register long lCumulative;
    /* Sum of iWritten's */

  TEST_ARG(iFrom > -1, 1);
  TEST_ARG(iTo   > -1, 2);
    /* test parameters to ensure we are not working with garbage ... */
  
  errno = 0;
    /* So that file limit returns 0 errno */
  lCumulative = 0;
  
  while ((iRead = read (iFrom, szBuffer, sizeof (szBuffer))) != 0)
  {
    if (iRead < 0)
      return (-1L);
    
    if ((iWritten = write (iTo, szBuffer, iRead)) != iRead)
    {
      ERROR_RESOURCE(INFO, GET_MESSAGE(NQSM_FILEIO_WRITE), iRead, iWritten, errno);
        /* 
	 * here, we now abort the daemon with a fatal error
	 * perhaps this is a little harsh?
	 */
    }
    lCumulative += iWritten;
  }
  return (lCumulative);
}


/*** filecopysized
 *
 *
 *	int filecopysized():
 *	Copy a file from one open file descriptor to another.
 *	Stop as soon as the specified number of bytes have been moved.
 *
 *	Returns:
 *	      >=0: if successful, or if it reached a premature EOF
 *		   (number of bytes transferred);
 *	       -1: if an error occurs (in which case errno is set).
 *		   Errno will equal zero, if we simply ran out of
 *		   file space writing the copy.
 */
long filecopysized (int from, int to, long bytes)
{
	char buffer [8192];		/* Copy buffer */
	register int nread;		/* One time number of bytes read */
	register int nwritten;		/* One time number of bytes written */
	register long need;		/* Number of bytes still needed */

	errno = 0;			/* So that file limit returns 0 errno */
	for (need = bytes; need > 0; need -= nwritten) {
		if ((nread = read (from, buffer,
			need < sizeof buffer ? need : sizeof buffer)) != 0) {
			if (nread < 0) return (-1L);
			if ((nwritten = write (to, buffer, nread)) != nread)
				return (-1L);
		}
		else return (bytes - need);
	}
	return (bytes);
}
