14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #include "sfhdr.h"
234887Schin
244887Schin /* Seek function that knows discipline
254887Schin **
264887Schin ** Written by Kiem-Phong Vo.
274887Schin */
284887Schin #if __STD_C
sfsk(Sfio_t * f,Sfoff_t addr,int type,Sfdisc_t * disc)298462SApril.Chin@Sun.COM Sfoff_t sfsk(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
304887Schin #else
314887Schin Sfoff_t sfsk(f,addr,type,disc)
328462SApril.Chin@Sun.COM Sfio_t* f;
334887Schin Sfoff_t addr;
348462SApril.Chin@Sun.COM int type;
354887Schin Sfdisc_t* disc;
364887Schin #endif
374887Schin {
384887Schin Sfoff_t p;
394887Schin reg Sfdisc_t* dc;
404887Schin reg ssize_t s;
414887Schin reg int local, mode;
428462SApril.Chin@Sun.COM SFMTXDECL(f);
434887Schin
448462SApril.Chin@Sun.COM SFMTXENTER(f, (Sfoff_t)(-1));
454887Schin
464887Schin GETLOCAL(f,local);
474887Schin if(!local && !(f->bits&SF_DCDOWN))
484887Schin { if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0)
494887Schin SFMTXRETURN(f, (Sfoff_t)(-1));
504887Schin if(SFSYNC(f) < 0)
514887Schin SFMTXRETURN(f, (Sfoff_t)(-1));
524887Schin #ifdef MAP_TYPE
534887Schin if(f->mode == SF_READ && (f->bits&SF_MMAP) && f->data)
544887Schin { SFMUNMAP(f, f->data, f->endb-f->data);
554887Schin f->data = NIL(uchar*);
564887Schin }
574887Schin #endif
584887Schin f->next = f->endb = f->endr = f->endw = f->data;
594887Schin }
604887Schin
614887Schin if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) > SEEK_END)
624887Schin SFMTXRETURN(f, (Sfoff_t)(-1));
634887Schin
644887Schin for(;;)
654887Schin { dc = disc;
664887Schin if(f->flags&SF_STRING)
674887Schin { SFSTRSIZE(f);
684887Schin if(type == SEEK_SET)
694887Schin s = (ssize_t)addr;
704887Schin else if(type == SEEK_CUR)
714887Schin s = (ssize_t)(addr + f->here);
724887Schin else s = (ssize_t)(addr + f->extent);
734887Schin }
744887Schin else
754887Schin { SFDISC(f,dc,seekf);
764887Schin if(dc && dc->seekf)
774887Schin { SFDCSK(f,addr,type,dc,p);
784887Schin }
794887Schin else
804887Schin { p = syslseekf(f->file,(sfoff_t)addr,type);
814887Schin }
824887Schin if(p >= 0)
834887Schin SFMTXRETURN(f,p);
844887Schin s = -1;
854887Schin }
864887Schin
874887Schin if(local)
884887Schin SETLOCAL(f);
894887Schin switch(_sfexcept(f,SF_SEEK,s,dc))
904887Schin {
914887Schin case SF_EDISC:
924887Schin case SF_ECONT:
934887Schin if(f->flags&SF_STRING)
944887Schin SFMTXRETURN(f, (Sfoff_t)s);
954887Schin goto do_continue;
964887Schin default:
974887Schin SFMTXRETURN(f, (Sfoff_t)(-1));
984887Schin }
994887Schin
1004887Schin do_continue:
1014887Schin for(dc = f->disc; dc; dc = dc->disc)
1024887Schin if(dc == disc)
1034887Schin break;
1044887Schin disc = dc;
1054887Schin }
1064887Schin }
107