Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/lib/usys/lseek.c
There are 10 other files named lseek.c in the archive. Click here to see a list.
/*
**	LSEEK - move read/write pointer
**
**	(c) Copyright Ken Harrenstien 1989
**		for all changes after v.36, 20-Sep-1988
**	(c) Copyright Ian Macky, SRI International 1986
**	Edits for ITS:  Copyright (C) 1988 Alan Bawden
**
*/

#include <c-env.h>
#if SYS_T20+SYS_10X+SYS_ITS+SYS_T10+SYS_WTS+SYS_CSI	/* Systems supported */

#include <sys/usysio.h>
#include <sys/usysig.h>
#include <sys/file.h>	/* Defines L_ flag values */
#include <errno.h>
#if SYS_T20+SYS_10X
#include <jsys.h>
#elif SYS_ITS
#include <sysits.h>
#elif SYS_T10+SYS_WTS+SYS_CSI
#include <uuosym.h>
#endif

long
lseek(fd, offset, whence)
int fd, whence;
long offset;
{
    register struct _ufile *uf;
    long newpos;		/* Return value must be on stack
				** (cannot use uf->uf_pos because interrupt
				** during USYS_RET might change that loc)
				*/

#if SYS_T20+SYS_10X
    int acs[5], fdb[2];
    extern long _nfbsz();	/* from STAT.C */
#elif SYS_ITS
    int syspos, skipcount;
    char gubbish[35];		/* can't need to skip more than 35 bytes */
#elif SYS_T10+SYS_WTS+SYS_CSI

#endif


    USYS_BEG();

    if (!(uf = _UFGET(fd)))
	USYS_RETERR(EBADF);

    switch (whence) {
	case L_SET:
	    newpos = offset;
	    break;
	case L_INCR:
	    newpos = uf->uf_pos + offset;
	    break;
	case L_XTND:
#if SYS_T20+SYS_10X
	    acs[1] = uf->uf_ch;
	    acs[2] = XWD(2,monsym(".FBBYV"));	/* Get .FBBYV, .FBSIZ */
	    acs[3] = (int) fdb;
	    if (!jsys(GTFDB, acs))
		USYS_RETERR(EBADF);
	    newpos = _nfbsz(uf->uf_bsize,	/* Derive # bytes */
				FLDGET(fdb[0], monsym("FB%BSZ")),
				fdb[1]);
	    if (newpos < uf->uf_pos)	/* If our len info is better */
		newpos = uf->uf_pos;	/* update it! */
	    newpos += offset;
	    break;
#elif SYS_WTS+SYS_CSI+SYS_T10
	    newpos = uf->uf_flen + offset;	/* Lots of luck */
	    break;
#elif SYS_ITS
	    /* ITS wants perfection but can't find exact EOF yet, so fails */
#endif
	default:
	    USYS_RETERR(EINVAL);
    }
    if (newpos == uf->uf_pos)		/* If not going anywhere, */
	USYS_RET(newpos);		/* we win immediately! */
    if (newpos < 0)			/* Sanity check */
	USYS_RETERR(EINVAL);

#if SYS_T20+SYS_10X
    acs[1] = uf->uf_ch;			/* JFN */
    acs[2] = newpos;
    if (!jsys(SFPTR, acs))		/* Set the file pointer */
	USYS_RETERR(EBADF);
    uf->uf_eof = 0;			/* Clear EOF indicator */
    uf->uf_rleft = uf->uf_wleft = 0;	/* Force read/write to seek */
    uf->uf_pos = newpos;		/* Set & return the new position */
    USYS_RET(newpos);


#elif SYS_T10+SYS_WTS+SYS_CSI
    if ((uf->uf_flgs & (UIOF_READ|UIOF_WRITE)) == UIOF_WRITE)
	USYS_RETERR(EBADF);		/* Cannot do write-only seeks */

    uf->uf_eof = 0;			/* Clear EOF indicator */
    uf->uf_rleft = uf->uf_wleft = 0;	/* Force read/write to seek */
    uf->uf_pos = newpos;		/* Set & return the new position */
    USYS_RET(newpos);
    

#elif SYS_ITS
    if (uf->uf_flgs & UIOF_HANDPACK) {
	syspos = newpos / uf->uf_nbpw;
	skipcount = newpos % uf->uf_nbpw;
	if (uf->uf_flgs & UIOF_WRITE) {
	    /* For block mode output, can only set position from one */
	    /* word boundary to another. */
	    if ((uf->uf_zcnt != 0) || (skipcount != 0))
		USYS_RETERR(EBADF);
	}
    } else {
	syspos = newpos;
	skipcount = 0;
    }
    
    if (SYSCALL2("access", uf->uf_ch, &syspos))
	USYS_RETERR(EBADF);

    uf->uf_eof = 0;			/* Clear EOF indicator */
    uf->uf_rleft = uf->uf_wleft = 0;	/* Force read/write to seek */
    uf->uf_pos = newpos;		/* Set & return the new position */
    uf->uf_zcnt = 0;			/* Sigh */

    if (skipcount != 0)
	if (read(fd, gubbish, skipcount) != skipcount)
	    USYS_RETERR(EIO);	/* now at neither new nor old position */

    USYS_RET(newpos);
#else

    USYS_RETERR(EINVAL);
#endif
}

long
tell(fd)
int fd;
{
    return lseek(fd, 0L, L_INCR);
}

#endif /* T20+10X+ITS+T10+WAITS+CSI */