#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <osbind.h>
#include <memory.h>
#include <string.h>
#include "lib.h"

#ifdef __GNUC__
#define alloca __builtin_alloca
#endif

static long _real_lseek(h, where, how)
int h;
long where;
int how;
{
    register long rv;
    
    rv = Fseek(where, h, how);
    if(rv < 0)
	errno = ((int) -rv);
    return(rv);
}

/*
 * emulate berzerkly lseek too
 */
long lseek(handle, offset, mode)
int handle;
long offset;
int mode;
{
    long current_pos;
    long expected_pos;
    long new_pos;
    char *buf;
    
    if ( (mode == SEEK_END) || (offset <= 0) )
	/* do it the usual way */
	return(_real_lseek(handle, offset, mode));
    
    current_pos = _real_lseek(handle, 0L, SEEK_CUR); /* find out where we are */
    if (mode == SEEK_SET)
	expected_pos = offset;
    else
	expected_pos = offset + current_pos;
    new_pos = _real_lseek(handle, offset, mode);
    if (new_pos == expected_pos)
	return(new_pos);
    
    /* otherwise extend file -- zero filling the hole */
    if (new_pos < 0)		/* error? */
    {
	new_pos = _real_lseek(handle, 0L, SEEK_END);	/* go to eof */
    }	
    
    buf  = (char *)alloca((size_t)256);
    bzero(buf, (size_t)256);
    while (expected_pos > new_pos)	
    {
	offset = expected_pos - new_pos;
	if (offset > 256) 
	    offset = 256;
	if((current_pos = _write(handle, buf, offset)) != offset)
	    return((current_pos > 0) ? (new_pos + current_pos) :
		   new_pos);	/* errno set by write */
	new_pos += offset;
    }
    return(new_pos);  
}

long tell(h)
int h;
{
    return(_real_lseek(h, 0L, SEEK_CUR));
}
