Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtksh / ksh93 / src / lib / libast / sfio / sfseek.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: sfseek.c /main/3 1995/11/01 18:35:35 rswiston $ */
24 /***************************************************************
25 *                                                              *
26 *                      AT&T - PROPRIETARY                      *
27 *                                                              *
28 *         THIS IS PROPRIETARY SOURCE CODE LICENSED BY          *
29 *                          AT&T CORP.                          *
30 *                                                              *
31 *                Copyright (c) 1995 AT&T Corp.                 *
32 *                     All Rights Reserved                      *
33 *                                                              *
34 *           This software is licensed by AT&T Corp.            *
35 *       under the terms and conditions of the license in       *
36 *       http://www.research.att.com/orgs/ssr/book/reuse        *
37 *                                                              *
38 *               This software was created by the               *
39 *           Software Engineering Research Department           *
40 *                    AT&T Bell Laboratories                    *
41 *                                                              *
42 *               For further information contact                *
43 *                     gsf@research.att.com                     *
44 *                                                              *
45 ***************************************************************/
46 #include        "sfhdr.h"
47
48 /*      Set the IO pointer to a specific location in the stream
49 **
50 **      Written by Kiem-Phong Vo (06/27/90)
51 */
52
53 #if __STD_C
54 long sfseek(reg Sfio_t* f, reg long p, reg int type)
55 #else
56 long sfseek(f,p,type)
57 reg Sfio_t      *f;     /* seek to a new location in this stream */
58 reg long        p;      /* place to seek to */
59 int             type;   /* 0: from org, 1: from here, 2: from end */
60 #endif
61 {
62         reg long        r, s;
63         reg int         mode, local;
64
65         GETLOCAL(f,local);
66
67         /* set and initialize the stream to a definite mode */
68         if(SFMODE(f,local) != (mode = f->mode&SF_RDWR) && _sfmode(f,mode,local) < 0 )
69                 return -1L;
70
71         if(type < 0 || type > 2 || f->extent < 0L)
72                 return -1L;
73
74         /* throw away ungetc data */
75         if(f->disc == _Sfudisc)
76                 (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
77
78         /* lock the stream for internal manipulations */
79         SFLOCK(f,local);
80
81         /* clear error and eof bits */
82         f->flags &= ~(SF_EOF|SF_ERROR);
83
84         while(f->flags&SF_STRING)
85         {       SFSTRSIZE(f);
86
87                 if(type == 1)
88                         r = p + (f->next - f->data);
89                 else if(type == 2)
90                         r = p + f->extent;
91                 else    r = p;
92
93                 if(r >= 0 && r <= f->size)
94                 {       p = r;
95                         f->next = f->data+p;
96                         f->here = p;
97                         if(p > f->extent)
98                                 memclear((char*)(f->data+f->extent),(int)(p-f->extent));
99                         goto done;
100                 }
101
102                 /* check exception handler, note that this may pop stream */
103                 if(SFSK(f,r,0,f->disc) != 0)
104                 {       p = -1L;
105                         goto done;
106                 }
107         }
108
109         /* flush any pending write data */
110         if((f->mode&SF_WRITE) && f->next > f->data && SFSYNC(f) < 0)
111         {       p = -1L;
112                 goto done;
113         }
114
115         /* currently known seek location */
116         if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC))
117         {       s = SFSK(f,0L,1,f->disc);
118                 if(s == f->here)
119                         goto logical_seek;
120         }
121         else
122         { logical_seek :
123                 s = f->here + ((f->mode&SF_READ) ? f->next-f->endb : f->next-f->data);
124         }
125
126         /* no need to do anything */
127         if(!(f->flags&SF_SHARE) && type == 0 && s == p)
128                 goto done;
129
130 #ifdef MAP_TYPE
131         if(f->flags&SF_MMAP)
132         {       /* move buffer pointer if possible */
133                 p += type == 0 ? 0L : type == 1 ? s : f->extent;
134                 if(p >= (f->here - (f->endb-f->data)) && p < f->here)
135                         f->next = f->endb - (f->here - p);
136                 else if(p >= 0)
137                 {       if(!(f->flags&SF_SHARE) || SFSK(f,p,0,f->disc) == p)
138                                 f->here = p;
139
140                         /* map is now invalid */
141                         if(f->data)
142                         {       (void)munmap((caddr_t)f->data,f->endb-f->data);
143                                 f->endb = f->endr = f->endw =
144                                 f->next = f->data = NIL(uchar*);
145                         }
146                 }
147
148                 goto done;
149         }
150 #endif
151
152         if(type == 1 && p == 0 && !(f->flags&(SF_APPEND|SF_SHARE)) )
153         {       /* certify current location only */
154                 if((p = SFSK(f,f->here,0,f->disc)) != f->here)
155                         p = -1L;
156                 else    p = s;
157                 goto done;
158         }
159
160         if(f->mode&SF_WRITE)
161         {       if(!(f->flags&SF_SHARE) && type < 2 && ((r = type == 0 ? p : p+s)) == s)
162                 {       /* at where we are supposed to be */
163                         p = r;
164                         goto done;
165                 }
166         }
167         else if(type < 2 && !(f->flags&(SF_SHARE|SF_APPEND)) &&
168                 (r = p + (type == 0 ? 0L : s)) > f->here && r < f->extent)
169         {       /* move forward by reading */
170                 if(f->next == f->endb)
171                         f->endb = f->endr = f->next = f->data;
172                 if(r < (s + (f->size - (f->endb-f->data))))
173                         (void)SFFILBUF(f,-1);
174         }
175
176         if(type < 2)
177         {       /* place to seek to */  
178                 p += type == 0 ? 0L : s;
179
180                 if((f->mode&SF_READ) && !(f->flags&(SF_SHARE|SF_APPEND)) &&
181                    p >= (f->here - (f->endb-f->data)) && p <= f->here)
182                 {       /* still in bound, safe to just move the pointer */
183                         f->next = f->endb - (f->here-p);
184                         goto done;
185                 }
186         }
187         else
188         {       if((p = SFSK(f,p,2,f->disc)) < 0)
189                         goto done;
190                 f->here = p;
191         }
192
193         if(f->mode&SF_READ)
194         {       /* any buffered data is invalid */
195                 f->next = f->endr = f->endb = f->data;
196
197                 /* seek to a rounded boundary to improve performance */
198                 if(f->size > 1 && p < f->extent && (r = (p/f->size)*f->size) < p &&
199                    SFSK(f,r,0,f->disc) == r)
200                 {       f->here = r;
201                         SFFILBUF(f,-1);
202                         if(f->here < p)
203                                 p = -1L;
204                         else    f->next = f->endb - (f->here-p);
205                         goto done;
206                 }
207         }
208
209         /* if get here must do a seek */
210         if(type < 2 && (p = SFSK(f,p,0,f->disc)) >= 0)
211                 f->here = p;
212
213 done :
214         SFOPEN(f,local);
215         return p;
216 }