xref: /titanic_41/usr/src/lib/libast/common/sfio/sfsk.c (revision d29f5a711240f866521445b1656d114da090335e)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
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
29 Sfoff_t sfsk(reg Sfio_t* f, Sfoff_t addr, reg int type, Sfdisc_t* disc)
30 #else
31 Sfoff_t sfsk(f,addr,type,disc)
32 reg Sfio_t*	f;
33 Sfoff_t		addr;
34 reg int		type;
35 Sfdisc_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 
43 	SFMTXSTART(f, (Sfoff_t)(-1));
44 
45 	GETLOCAL(f,local);
46 	if(!local && !(f->bits&SF_DCDOWN))
47 	{	if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0)
48 			SFMTXRETURN(f, (Sfoff_t)(-1));
49 		if(SFSYNC(f) < 0)
50 			SFMTXRETURN(f, (Sfoff_t)(-1));
51 #ifdef MAP_TYPE
52 		if(f->mode == SF_READ && (f->bits&SF_MMAP) && f->data)
53 		{	SFMUNMAP(f, f->data, f->endb-f->data);
54 			f->data = NIL(uchar*);
55 		}
56 #endif
57 		f->next = f->endb = f->endr = f->endw = f->data;
58 	}
59 
60 	if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) > SEEK_END)
61 		SFMTXRETURN(f, (Sfoff_t)(-1));
62 
63 	for(;;)
64 	{	dc = disc;
65 		if(f->flags&SF_STRING)
66 		{	SFSTRSIZE(f);
67 			if(type == SEEK_SET)
68 				s = (ssize_t)addr;
69 			else if(type == SEEK_CUR)
70 				s = (ssize_t)(addr + f->here);
71 			else	s = (ssize_t)(addr + f->extent);
72 		}
73 		else
74 		{	SFDISC(f,dc,seekf);
75 			if(dc && dc->seekf)
76 			{	SFDCSK(f,addr,type,dc,p);
77 			}
78 			else
79 			{	p = syslseekf(f->file,(sfoff_t)addr,type);
80 			}
81 			if(p >= 0)
82 				SFMTXRETURN(f,p);
83 			s = -1;
84 		}
85 
86 		if(local)
87 			SETLOCAL(f);
88 		switch(_sfexcept(f,SF_SEEK,s,dc))
89 		{
90 		case SF_EDISC:
91 		case SF_ECONT:
92 			if(f->flags&SF_STRING)
93 				SFMTXRETURN(f, (Sfoff_t)s);
94 			goto do_continue;
95 		default:
96 			SFMTXRETURN(f, (Sfoff_t)(-1));
97 		}
98 
99 	do_continue:
100 		for(dc = f->disc; dc; dc = dc->disc)
101 			if(dc == disc)
102 				break;
103 		disc = dc;
104 	}
105 }
106