#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stddef.h>
#include "file2.h"
#include "internal.h"

#include <trace.h>
/**************************************************************************
 *
 * Function:    ftell
 *
 * Description:
 *     Return the current position of the file
 *
 * Entry:
 *     fpStream   - Pointer to the stream to measure
 *
 * Returns:
 *     The number of bytes since the start of the file or -1 to indicate
 *     an error or EOF condition.
 */

long ftell (FILE *fpStream)
    {
    int   lOffset;
    long  lFilePos;
    int   nFd;
    int   nReadCount;
    long  lAnswer = -2L;
    FUNC_ENTRY ("ftell");
/*
 *  If the buffer is undefined then make the count legal
 */
    if (fpStream->_cnt < 0)
        {
	fpStream->_cnt = 0;
        }
/*
 *  Obtain the file number for the seek operation.
 */
    nFd = fileno (fpStream);
/*
 *  Compute the relative location for the current buffer.
 */
    lFilePos = lseek (nFd, 0L, SEEK_CUR);
    if (lFilePos < 0L)
        {
	lAnswer = -1L;
        }
/*
 *  If the file is not buffered then use only the space in the buffer.
 */
    if (lAnswer == -2L)
        {
	if (!bigbuf (fpStream))
	    {
	    lAnswer = lFilePos - fpStream->_cnt;
	    }
        }
/*
 *  Compute the lOffset relative to the buffer
 */
    if (lAnswer == -2L)
        {
	lOffset = fpStream->_ptr - fpStream->_base;
	if ((fpStream->_flag & (_IORW | _IOREAD | _IOWRT)) == 0)
	    {
	    errno   = EINVAL;
	    lAnswer = -1L;
	    }
        }
/*
 *  If the pointer is relative to the start of the buffer then compute
 *  the base address of the position as the first byte of the buffer area.
 */
    if (lAnswer == -2L && lFilePos == 0L)
        {
	lAnswer = lOffset;
        }
/*
 *  Adjust the position if the file is in "read" mode.
 */
    if (lAnswer == -2L)
        {
	  /* Must be careful here - seek leaves the file in neither state. */
	if (!(fpStream->_flag & _IOWRT))
	    {
	    if (fpStream->_cnt == 0)
	        {
		lOffset = 0L;
	        }
/*
 *  The file is in write mode. Update the count relative to the space written
 *  and the relative byte lOffset for the current record.
 */
	    else
	        {
		nReadCount = fpStream->_cnt +
		             (fpStream->_ptr - fpStream->_base);

		lFilePos  -= (long) nReadCount;
	        }
	    }
	lAnswer = lFilePos + lOffset;
        }
/*
 *  Return the file position.
 */
    FUNC_EXIT ("ftell");
    return (lAnswer);
    }
