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 /* Read n bytes from a stream into a buffer
26 ** Written by Kiem-Phong Vo.
30 ssize_t
sfread(Sfio_t
* f
, Void_t
* buf
, size_t n
)
32 ssize_t
sfread(f
,buf
,n
)
33 Sfio_t
* f
; /* read from this stream. */
34 Void_t
* buf
; /* buffer to read into */
35 size_t n
; /* number of bytes to be read. */
40 reg
int local
, justseek
;
43 SFMTXENTER(f
, (ssize_t
)(-1));
46 justseek
= f
->bits
&SF_JUSTSEEK
; f
->bits
&= ~SF_JUSTSEEK
;
49 SFMTXRETURN(f
, (ssize_t
)(n
== 0 ? 0 : -1) );
51 /* release peek lock */
53 { if(!(f
->mode
&SF_READ
) )
54 SFMTXRETURN(f
, (ssize_t
)(-1));
57 { if(((uchar
*)buf
+ f
->val
) != f
->next
&&
58 (!f
->rsrv
|| f
->rsrv
->data
!= (uchar
*)buf
) )
59 SFMTXRETURN(f
, (ssize_t
)(-1));
64 { if((uchar
*)buf
!= f
->next
)
65 SFMTXRETURN(f
, (ssize_t
)(-1));
68 { /* actually read the data now */
71 n
= (r
= sysreadf(f
->file
,f
->data
,n
)) < 0 ? 0 : r
;
81 s
= begs
= (uchar
*)buf
;
82 for(;; f
->mode
&= ~SF_LOCK
)
83 { /* check stream mode */
84 if(SFMODE(f
,local
) != SF_READ
&& _sfmode(f
,SF_READ
,local
) < 0)
85 { n
= s
> begs
? s
-begs
: (size_t)(-1);
86 SFMTXRETURN(f
, (ssize_t
)n
);
91 if((r
= f
->endb
- f
->next
) > 0) /* has buffered data */
95 memcpy(s
, f
->next
, r
);
101 if(n
<= 0) /* all done */
104 if(!(f
->flags
&SF_STRING
) && !(f
->bits
&SF_MMAP
) )
105 { f
->next
= f
->endb
= f
->data
;
107 /* exact IO is desirable for these cases */
109 ((f
->flags
&SF_SHARE
) && f
->extent
< 0) )
111 else if(justseek
&& n
<= f
->iosz
&& f
->iosz
<= f
->size
)
112 r
= f
->iosz
; /* limit buffering */
113 else r
= f
->size
; /* full buffering */
115 /* if read almost full size, then just do it direct */
116 if(r
> (ssize_t
)n
&& (r
- r
/8) <= (ssize_t
)n
)
119 /* read directly to user's buffer */
120 if(r
== (ssize_t
)n
&& (r
= SFRD(f
,s
,r
,f
->disc
)) >= 0)
123 if(r
== 0 || n
== 0) /* eof or eob */
131 f
->bits
|= SF_JUSTSEEK
;
132 if(SFFILBUF(f
,-1) <= 0)