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 with discipline.
26 ** Written by Kiem-Phong Vo.
29 /* hole preserving writes */
31 static ssize_t
sfoutput(Sfio_t
* f
, char* buf
, size_t n
)
33 static ssize_t
sfoutput(f
,buf
,n
)
38 { reg
char *sp
, *wbuf
, *endbuf
;
45 { if((ssize_t
)n
< _Sfpage
) /* no hole possible */
49 else while((ssize_t
)n
>= _Sfpage
)
50 { /* see if a hole of 0's starts here */
52 if(buf
[0] == 0 && buf
[_Sfpage
-1] == 0)
53 { /* check byte at a time until int-aligned */
54 while(((ulong
)sp
)%sizeof(int))
60 /* check using int to speed up */
62 { if(*((int*)sp
) != 0)
67 /* check the remaining bytes */
79 if((s
= sp
-buf
) >= _Sfpage
) /* found a hole */
82 /* skip a dirty page */
87 /* write out current dirty pages */
89 { if((ssize_t
)n
< _Sfpage
)
93 if((wr
= syswritef(f
->file
,wbuf
,buf
-wbuf
)) > 0)
102 /* seek to a rounded boundary within the hole */
104 { s
= (s
/_Sfpage
)*_Sfpage
;
105 if(SFSK(f
,(Sfoff_t
)s
,SEEK_CUR
,NIL(Sfdisc_t
*)) < 0)
113 { /* next page must be dirty */
114 s
= (ssize_t
)n
<= _Sfpage
? 1 : _Sfpage
;
121 return w
> 0 ? w
: -1;
125 ssize_t
sfwr(Sfio_t
* f
, const Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
127 ssize_t
sfwr(f
,buf
,n
,disc
)
136 reg
int local
, oerrno
;
139 SFMTXENTER(f
,(ssize_t
)(-1));
142 if(!local
&& !(f
->bits
&SF_DCDOWN
)) /* an external user's call */
143 { if(f
->mode
!= SF_WRITE
&& _sfmode(f
,SF_WRITE
,0) < 0 )
144 SFMTXRETURN(f
, (ssize_t
)(-1));
145 if(f
->next
> f
->data
&& SFSYNC(f
) < 0 )
146 SFMTXRETURN(f
, (ssize_t
)(-1));
150 { /* stream locked by sfsetfd() */
151 if(!(f
->flags
&SF_STRING
) && f
->file
< 0)
152 SFMTXRETURN(f
,(ssize_t
)0);
154 /* clear current error states */
155 f
->flags
&= ~(SF_EOF
|SF_ERROR
);
158 if(f
->flags
&SF_STRING
) /* total required buffer */
159 w
= n
+ (f
->next
- f
->data
);
161 { /* warn that a write is about to happen */
163 if(dc
&& dc
->exceptf
&& (f
->flags
&SF_IOCHECK
) )
167 if((rv
= _sfexcept(f
,SF_WRITE
,n
,dc
)) > 0)
170 { f
->flags
|= SF_ERROR
;
176 { /* make sure we are at the right place to write */
177 if(f
->flags
&SF_APPENDWR
)
178 { if(f
->here
!= f
->extent
|| (f
->flags
&SF_SHARE
))
179 { f
->here
= SFSK(f
,(Sfoff_t
)0,SEEK_END
,dc
);
183 else if((f
->flags
&SF_SHARE
) && !(f
->flags
&SF_PUBLIC
))
184 f
->here
= SFSK(f
,f
->here
,SEEK_SET
,dc
);
191 { SFDCWR(f
,buf
,n
,dc
,w
);
195 else if(f
->flags
&SF_WHOLE
)
197 else if((ssize_t
)n
>= _Sfpage
&&
198 !(f
->flags
&(SF_SHARE
|SF_APPENDWR
)) &&
199 f
->here
== f
->extent
&& (f
->here
%_Sfpage
) == 0)
200 { if((w
= sfoutput(f
,(char*)buf
,n
)) <= 0)
206 if((w
= syswritef(f
->file
,buf
,n
)) > 0)
214 { if(!(f
->bits
&SF_DCDOWN
) )
215 { if((f
->flags
&(SF_APPENDWR
|SF_PUBLIC
)) && f
->extent
>= 0 )
216 f
->here
= SFSK(f
,(Sfoff_t
)0,SEEK_CUR
,dc
);
218 if(f
->extent
>= 0 && f
->here
> f
->extent
)
222 SFMTXRETURN(f
, (ssize_t
)w
);
228 switch(_sfexcept(f
,SF_WRITE
,w
,dc
))
234 SFMTXRETURN(f
, (ssize_t
)w
);
236 if(!local
&& !(f
->flags
&SF_STRING
))
240 SFMTXRETURN(f
, (ssize_t
)(-1));
244 for(dc
= f
->disc
; dc
; dc
= dc
->disc
)