1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                  Common Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*            http://www.opensource.org/licenses/cpl1.0.txt             *
11*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22#include	"sfhdr.h"
23
24/*	Seek function that knows discipline
25**
26**	Written by Kiem-Phong Vo.
27*/
28#if __STD_C
29Sfoff_t sfsk(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
30#else
31Sfoff_t sfsk(f,addr,type,disc)
32Sfio_t*		f;
33Sfoff_t		addr;
34int		type;
35Sfdisc_t*	disc;
36#endif
37{
38	Sfoff_t		p;
39	reg Sfdisc_t*	dc;
40	reg ssize_t	s;
41	reg int		local, mode;
42	SFMTXDECL(f);
43
44	SFMTXENTER(f, (Sfoff_t)(-1));
45
46	GETLOCAL(f,local);
47	if(!local && !(f->bits&SF_DCDOWN))
48	{	if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0)
49			SFMTXRETURN(f, (Sfoff_t)(-1));
50		if(SFSYNC(f) < 0)
51			SFMTXRETURN(f, (Sfoff_t)(-1));
52#ifdef MAP_TYPE
53		if(f->mode == SF_READ && (f->bits&SF_MMAP) && f->data)
54		{	SFMUNMAP(f, f->data, f->endb-f->data);
55			f->data = NIL(uchar*);
56		}
57#endif
58		f->next = f->endb = f->endr = f->endw = f->data;
59	}
60
61	if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) > SEEK_END)
62		SFMTXRETURN(f, (Sfoff_t)(-1));
63
64	for(;;)
65	{	dc = disc;
66		if(f->flags&SF_STRING)
67		{	SFSTRSIZE(f);
68			if(type == SEEK_SET)
69				s = (ssize_t)addr;
70			else if(type == SEEK_CUR)
71				s = (ssize_t)(addr + f->here);
72			else	s = (ssize_t)(addr + f->extent);
73		}
74		else
75		{	SFDISC(f,dc,seekf);
76			if(dc && dc->seekf)
77			{	SFDCSK(f,addr,type,dc,p);
78			}
79			else
80			{	p = syslseekf(f->file,(sfoff_t)addr,type);
81			}
82			if(p >= 0)
83				SFMTXRETURN(f,p);
84			s = -1;
85		}
86
87		if(local)
88			SETLOCAL(f);
89		switch(_sfexcept(f,SF_SEEK,s,dc))
90		{
91		case SF_EDISC:
92		case SF_ECONT:
93			if(f->flags&SF_STRING)
94				SFMTXRETURN(f, (Sfoff_t)s);
95			goto do_continue;
96		default:
97			SFMTXRETURN(f, (Sfoff_t)(-1));
98		}
99
100	do_continue:
101		for(dc = f->disc; dc; dc = dc->disc)
102			if(dc == disc)
103				break;
104		disc = dc;
105	}
106}
107