/*
 * libnqs/req/writehdr.c
 * 
 * DESCRIPTION:
 *
 *	[Re]write the common header portion of a request control
 *	file.
 *
 *	Original Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	August 12, 1985.
 */

#include <libnqs/license.h>
#include <libnqs/proto.h>
#include <errno.h>
#include <unistd.h>


/*** writehdr
 *
 *
 *	int writehdr():
 *
 *	[Re]write the common header portion of a request control
 *	file.
 *
 *	Unless errno is returned non-zero, the lseek() position
 *	of the control file descriptor upon return, is ALWAYS at
 *	the first byte of the varying portion of the control file.
 *
 *
 *	Returns:
 *		0: if successful;
 *	       -1: otherwise.
 *
 *			Note:  errno will be returned 0 by this function
 *			       unless a system call error has occurred.
 */
int writehdr (int fd, struct rawreq *rawreq)
{
	register int size;		/* Size of common request header */

	errno = 0;
	if (lseek (fd, 0L, 0) == -1) {	/* Seek to start of control file */
		return (-1);		/* Return EBADF */
	}
	/*
	 *  [Re]write the common header portion of an NQS control file,
	 *  in one single write() system call.
	 *
	 *  We do this for reasons of efficiency, and also so that the first
	 *  block of the control file is [re]written in a single atomic
	 *  I/O operation so that Qmod updates, and multiple readers of
	 *  the control file (who are also carefully reading the first
	 *  block of the control in an indivisible fashion), will not
	 *  step on each other.
	 */
	size = ((char *) &rawreq->v) - ((char *) rawreq);
	if (write (fd, (char *) rawreq, size) != size) {
		if (errno == 0) {
			/*
			 *  We presume that the receiving device has been
			 *  completely filled-up, and artifically set errno
			 *  to ENOSPC, for the benefit of the caller.
			 */
			errno = ENOSPC;	/* Insufficient space */
		}
		return (-1);		/* Write() failed */
	}
	/*
	 *  Leave the file pointer pointing at the varying part
	 *  of the request control file.
	 */
	if (rawreq->type == RTYPE_DEVICE) {
		/*
		 *  We are [re]writing the control file common
		 *  header of a device-oriented request.
		 */
		size = sizeof (struct rawdevreq);
	}
	else {
		/*
		 *  We are [re]writing the control file common
		 *  header of a non device-oriented request.
		 */
		size = sizeof (struct rawbatreq);
	}
	lseek (fd, (long) size, 1);	/* Relative seek */
	errno = 0;			/* Extreme paranoia */
	return (0);
}
