1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
24 /* Internal function to do a hard read.
25 ** This knows about discipline and memory mapping, peek read.
27 ** Written by Kiem-Phong Vo.
30 /* synchronize unseekable write streams */
32 static void _sfwrsync(void)
34 static void _sfwrsync()
40 /* sync all pool heads */
41 for(p
= _Sfpool
.next
; p
; p
= p
->next
)
45 if(!SFFROZEN(f
) && f
->next
> f
->data
&&
46 (f
->mode
&SF_WRITE
) && f
->extent
< 0 )
47 (void)_sfflsbuf(f
,-1);
50 /* and all the ones in the discrete pool */
51 for(n
= 0; n
< _Sfpool
.n_sf
; ++n
)
54 if(!SFFROZEN(f
) && f
->next
> f
->data
&&
55 (f
->mode
&SF_WRITE
) && f
->extent
< 0 )
56 (void)_sfflsbuf(f
,-1);
61 ssize_t
sfrd(Sfio_t
* f
, Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
63 ssize_t
sfrd(f
,buf
,n
,disc
)
72 reg
int local
, rcrv
, dosync
, oerrno
;
78 if((rcrv
= f
->mode
& (SF_RC
|SF_RV
)) )
79 f
->mode
&= ~(SF_RC
|SF_RV
);
80 f
->bits
&= ~SF_JUSTSEEK
;
85 if(!local
&& !(f
->bits
&SF_DCDOWN
)) /* an external user's call */
86 { if(f
->mode
!= SF_READ
&& _sfmode(f
,SF_READ
,0) < 0)
91 if((f
->mode
&(SF_SYNCED
|SF_READ
)) == (SF_SYNCED
|SF_READ
) )
92 { f
->endb
= f
->next
= f
->endr
= f
->data
;
93 f
->mode
&= ~SF_SYNCED
;
96 if((f
->bits
&SF_MMAP
) && f
->data
)
97 { SFMUNMAP(f
, f
->data
, f
->endb
-f
->data
);
98 f
->data
= NIL(uchar
*);
101 f
->next
= f
->endb
= f
->endr
= f
->endw
= f
->data
;
106 { /* stream locked by sfsetfd() */
107 if(!(f
->flags
&SF_STRING
) && f
->file
< 0)
110 f
->flags
&= ~(SF_EOF
|SF_ERROR
);
113 if(f
->flags
&SF_STRING
)
114 { if((r
= (f
->data
+f
->extent
) - f
->next
) < 0)
118 SFMTXRETURN(f
, (ssize_t
)r
);
121 /* warn that a read is about to happen */
123 if(dc
&& dc
->exceptf
&& (f
->flags
&SF_IOCHECK
) )
127 if((rv
= _sfexcept(f
,SF_READ
,n
,dc
)) > 0)
130 { f
->flags
|= SF_ERROR
;
131 SFMTXRETURN(f
, (ssize_t
)rv
);
137 { reg ssize_t a
, round
;
140 /* determine if we have to copy data to buffer */
141 if((uchar
*)buf
>= f
->data
&& (uchar
*)buf
<= f
->endb
)
142 { n
+= f
->endb
- f
->next
;
146 /* actual seek location */
147 if((f
->flags
&(SF_SHARE
|SF_PUBLIC
)) == (SF_SHARE
|SF_PUBLIC
) &&
148 (r
= SFSK(f
,(Sfoff_t
)0,SEEK_CUR
,dc
)) != f
->here
)
150 else f
->here
-= f
->endb
-f
->next
;
152 /* before mapping, make sure we have data to map */
153 if((f
->flags
&SF_SHARE
) || (size_t)(r
= f
->extent
-f
->here
) < n
)
154 { if((r
= sysfstatf(f
->file
,&st
)) < 0)
156 if((r
= (f
->extent
= st
.st_size
) - f
->here
) <= 0 )
162 /* make sure current position is page aligned */
163 if((a
= (size_t)(f
->here
%_Sfpage
)) != 0)
168 /* map minimal requirement */
169 if(r
> (round
= (1 + (n
+a
)/f
->size
)*f
->size
) )
173 SFMUNMAP(f
, f
->data
, f
->endb
-f
->data
);
176 { f
->data
= (uchar
*) sysmmapf((caddr_t
)0, (size_t)r
,
177 (PROT_READ
|PROT_WRITE
),
179 f
->file
, (sfoff_t
)f
->here
);
180 if(f
->data
&& (caddr_t
)f
->data
!= (caddr_t
)(-1))
183 { f
->data
= NIL(uchar
*);
184 if((r
>>= 1) < (_Sfpage
*SF_NMAP
) ||
185 (errno
!= EAGAIN
&& errno
!= ENOMEM
) )
191 { if(f
->bits
&SF_SEQUENTIAL
)
192 SFMMSEQON(f
,f
->data
,r
);
194 f
->endr
= f
->endb
= f
->data
+r
;
198 /* make known our seek location */
199 (void)SFSK(f
,f
->here
,SEEK_SET
,dc
);
202 { if(n
> (size_t)(r
-a
))
204 memcpy(buf
,f
->next
,n
);
207 else n
= f
->endb
- f
->next
;
215 /* reset seek pointer to its physical location */
216 (void)SFSK(f
,f
->here
,SEEK_SET
,dc
);
219 (void)SFSETBUF(f
,(Void_t
*)f
->tiny
,(size_t)SF_UNBOUND
);
222 { buf
= (Void_t
*)f
->data
;
229 /* sync unseekable write streams to prevent deadlock */
230 if(!dosync
&& f
->extent
< 0)
235 /* make sure file pointer is right */
236 if(f
->extent
>= 0 && (f
->flags
&SF_SHARE
) )
237 { if(!(f
->flags
&SF_PUBLIC
) )
238 f
->here
= SFSK(f
,f
->here
,SEEK_SET
,dc
);
239 else f
->here
= SFSK(f
,(Sfoff_t
)0,SEEK_CUR
,dc
);
246 { int share
= f
->flags
&SF_SHARE
;
248 if(rcrv
) /* pass on rcrv for possible continuations */
250 /* tell readf that no peeking necessary */
251 else f
->flags
&= ~SF_SHARE
;
253 SFDCRD(f
,buf
,n
,dc
,r
);
258 else f
->flags
|= share
;
262 else if(f
->extent
< 0 && (f
->flags
&SF_SHARE
) && rcrv
)
263 { /* try peek read */
264 r
= sfpkrd(f
->file
, (char*)buf
, n
,
265 (rcrv
&SF_RC
) ? (int)f
->getr
: -1,
266 -1L, (rcrv
&SF_RV
) ? 1 : 0);
270 else f
->mode
|= SF_RC
;
273 else r
= sysreadf(f
->file
,buf
,n
);
279 { if(!(f
->bits
&SF_DCDOWN
) ) /* not a continuation call */
280 { if(!(f
->mode
&SF_PKRD
) )
282 if(f
->extent
>= 0 && f
->extent
< f
->here
)
285 if((uchar
*)buf
>= f
->data
&&
286 (uchar
*)buf
< f
->data
+f
->size
)
287 f
->endb
= f
->endr
= ((uchar
*)buf
) + r
;
290 SFMTXRETURN(f
, (ssize_t
)r
);
296 switch(_sfexcept(f
,SF_READ
,(ssize_t
)r
,dc
))
301 n
= local
? 0 : (ssize_t
)r
;
304 if(!local
&& !(f
->flags
&SF_STRING
))
312 for(dc
= f
->disc
; dc
; dc
= dc
->disc
)