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 /* Write data out to the file system
26 ** Written by Kiem-Phong Vo.
30 ssize_t
sfwrite(Sfio_t
* f
, const Void_t
* buf
, size_t n
)
32 ssize_t
sfwrite(f
,buf
,n
)
33 Sfio_t
* f
; /* write to this stream. */
34 Void_t
* buf
; /* buffer to be written. */
35 size_t n
; /* number of bytes. */
38 reg uchar
*s
, *begs
, *next
;
43 SFMTXENTER(f
, (ssize_t
)(-1));
48 SFMTXRETURN(f
, (ssize_t
)(n
== 0 ? 0 : -1) );
50 /* release peek lock */
52 { if(!(f
->mode
&SF_WRITE
) && (f
->flags
&SF_RDWR
) != SF_RDWR
)
53 SFMTXRETURN(f
, (ssize_t
)(-1));
55 if((uchar
*)buf
!= f
->next
&&
56 (!f
->rsrv
|| f
->rsrv
->data
!= (uchar
*)buf
) )
57 SFMTXRETURN(f
, (ssize_t
)(-1));
62 { /* read past peeked data */
67 { if((r
= w
) > sizeof(buf
))
69 if((r
= sysreadf(f
->file
,buf
,r
)) <= 0)
77 f
->endb
= f
->data
+ n
;
81 if((f
->mode
&SF_READ
) && f
->proc
)
85 s
= begs
= (uchar
*)buf
;
86 for(;; f
->mode
&= ~SF_LOCK
)
87 { /* check stream mode */
88 if(SFMODE(f
,local
) != SF_WRITE
&& _sfmode(f
,SF_WRITE
,local
) < 0 )
89 { w
= s
> begs
? s
-begs
: -1;
95 w
= f
->endb
- f
->next
;
97 if(s
== f
->next
) /* after sfreserve */
105 /* attempt to create space in buffer */
106 if(w
== 0 || ((f
->flags
&SF_WHOLE
) && w
< (ssize_t
)n
) )
107 { if(f
->flags
&SF_STRING
) /* extend buffer */
108 { (void)SFWR(f
, s
, n
-w
, f
->disc
);
109 if((w
= f
->endb
- f
->next
) < (ssize_t
)n
)
110 { if(!(f
->flags
&SF_STRING
)) /* maybe sftmp */
111 { if(f
->next
> f
->data
)
118 else if(f
->next
> f
->data
)
120 (void)SFFLSBUF(f
, -1);
121 if((w
= f
->endb
- f
->next
) < (ssize_t
)n
&&
122 (f
->flags
&SF_WHOLE
) && f
->next
> f
->data
)
127 if(!(f
->flags
&SF_STRING
) && f
->next
== f
->data
&&
128 (((f
->flags
&SF_WHOLE
) && w
<= n
) || SFDIRECT(f
,n
)) )
129 { /* bypass buffering */
130 if((w
= SFWR(f
,s
,n
,f
->disc
)) <= 0 )
136 if(w
<= 0) /* no forward progress possible */
138 memcpy(f
->next
, s
, w
);
147 /* always flush buffer for share streams */
148 if(f
->extent
< 0 && (f
->flags
&SF_SHARE
) && !(f
->flags
&SF_PUBLIC
) )
149 (void)SFFLSBUF(f
,-1);
151 /* check to see if buffer should be flushed */
152 else if(n
== 0 && (f
->flags
&SF_LINE
) && !(f
->flags
&SF_STRING
))
153 { if((ssize_t
)(n
= f
->next
-f
->data
) > (w
= s
-begs
))
155 if(n
> 0 && n
< HIFORLINE
)
156 { for(next
= f
->next
-1; n
> 0; --n
, --next
)
164 (void)SFFLSBUF(f
,-1);