1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*b30d1939SAndy Fiddaman * Copyright (c) 1985-2011 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html *
11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #if defined(__STDPP__directive) && defined(__STDPP__hide)
23da2e3ebdSchin __STDPP__directive pragma pp:hide getpagesize
24da2e3ebdSchin #else
25da2e3ebdSchin #define getpagesize ______getpagesize
26da2e3ebdSchin #endif
27da2e3ebdSchin
28da2e3ebdSchin #include "sfhdr.h"
29da2e3ebdSchin
30da2e3ebdSchin #if defined(__STDPP__directive) && defined(__STDPP__hide)
31da2e3ebdSchin __STDPP__directive pragma pp:nohide getpagesize
32da2e3ebdSchin #else
33da2e3ebdSchin #undef getpagesize
34da2e3ebdSchin #endif
35da2e3ebdSchin
36da2e3ebdSchin #if _lib_getpagesize
37da2e3ebdSchin _BEGIN_EXTERNS_
38da2e3ebdSchin extern int getpagesize _ARG_((void));
39da2e3ebdSchin _END_EXTERNS_
40da2e3ebdSchin #endif
41da2e3ebdSchin
42da2e3ebdSchin /* Set a (new) buffer for a stream.
43da2e3ebdSchin ** If size < 0, it is assigned a suitable value depending on the
44da2e3ebdSchin ** kind of stream. The actual buffer size allocated is dependent
45da2e3ebdSchin ** on how much memory is available.
46da2e3ebdSchin **
47da2e3ebdSchin ** Written by Kiem-Phong Vo.
48da2e3ebdSchin */
49da2e3ebdSchin
50da2e3ebdSchin #if !_sys_stat
51da2e3ebdSchin struct stat
52da2e3ebdSchin { int st_mode;
53da2e3ebdSchin int st_size;
54da2e3ebdSchin };
55da2e3ebdSchin #undef sysfstatf
56da2e3ebdSchin #define sysfstatf(fd,st) (-1)
57da2e3ebdSchin #endif /*_sys_stat*/
58da2e3ebdSchin
59*b30d1939SAndy Fiddaman #if _PACKAGE_ast && !defined(SFSETLINEMODE)
60*b30d1939SAndy Fiddaman #define SFSETLINEMODE 1
61*b30d1939SAndy Fiddaman #endif
62*b30d1939SAndy Fiddaman
63*b30d1939SAndy Fiddaman #if SFSETLINEMODE
64*b30d1939SAndy Fiddaman
sfsetlinemode()65*b30d1939SAndy Fiddaman static int sfsetlinemode()
66da2e3ebdSchin { char* astsfio;
67da2e3ebdSchin char* endw;
68da2e3ebdSchin
69da2e3ebdSchin static int modes = -1;
70da2e3ebdSchin static const char sf_line[] = "SF_LINE";
71*b30d1939SAndy Fiddaman static const char sf_maxr[] = "SF_MAXR=";
72da2e3ebdSchin static const char sf_wcwidth[] = "SF_WCWIDTH";
73da2e3ebdSchin
74da2e3ebdSchin #define ISSEPAR(c) ((c) == ',' || (c) == ' ' || (c) == '\t')
75da2e3ebdSchin if (modes < 0)
76da2e3ebdSchin { modes = 0;
77*b30d1939SAndy Fiddaman if(astsfio = getenv("SFIO_OPTIONS"))
78da2e3ebdSchin { for(; *astsfio != 0; astsfio = endw)
79da2e3ebdSchin { while(ISSEPAR(*astsfio) )
80*b30d1939SAndy Fiddaman ++astsfio;
81da2e3ebdSchin for(endw = astsfio; *endw && !ISSEPAR(*endw); ++endw)
82da2e3ebdSchin ;
83*b30d1939SAndy Fiddaman if((endw-astsfio) > (sizeof(sf_line)-1) &&
84*b30d1939SAndy Fiddaman strncmp(astsfio,sf_line,sizeof(sf_line)-1) == 0)
85*b30d1939SAndy Fiddaman modes |= SF_LINE;
86*b30d1939SAndy Fiddaman else if((endw-astsfio) > (sizeof(sf_maxr)-1) &&
87*b30d1939SAndy Fiddaman strncmp(astsfio,sf_maxr,sizeof(sf_maxr)-1) == 0)
88*b30d1939SAndy Fiddaman #if _PACKAGE_ast
89*b30d1939SAndy Fiddaman _Sfmaxr = (ssize_t)strtonll(astsfio+sizeof(sf_maxr)-1,NiL,NiL,0);
90*b30d1939SAndy Fiddaman #else
91*b30d1939SAndy Fiddaman _Sfmaxr = (ssize_t)strtol(astsfio+sizeof(sf_maxr)-1,NiL,0);
92*b30d1939SAndy Fiddaman #endif
93*b30d1939SAndy Fiddaman else if((endw-astsfio) > (sizeof(sf_wcwidth)-1) &&
94*b30d1939SAndy Fiddaman strncmp(astsfio,sf_wcwidth,sizeof(sf_wcwidth)-1) == 0)
95*b30d1939SAndy Fiddaman modes |= SF_WCWIDTH;
96da2e3ebdSchin }
97da2e3ebdSchin }
98da2e3ebdSchin }
99da2e3ebdSchin return modes;
100da2e3ebdSchin }
101da2e3ebdSchin
102*b30d1939SAndy Fiddaman #endif
103*b30d1939SAndy Fiddaman
104da2e3ebdSchin #if __STD_C
sfsetbuf(Sfio_t * f,Void_t * buf,size_t size)1057c2fbfb3SApril Chin Void_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size)
106da2e3ebdSchin #else
107da2e3ebdSchin Void_t* sfsetbuf(f,buf,size)
1087c2fbfb3SApril Chin Sfio_t* f; /* stream to be buffered */
1097c2fbfb3SApril Chin Void_t* buf; /* new buffer */
1107c2fbfb3SApril Chin size_t size; /* buffer size, -1 for default size */
111da2e3ebdSchin #endif
112da2e3ebdSchin {
113da2e3ebdSchin int sf_malloc, oflags, init, okmmap, local;
114da2e3ebdSchin ssize_t bufsize, blksz;
115da2e3ebdSchin Sfdisc_t* disc;
116da2e3ebdSchin sfstat_t st;
117da2e3ebdSchin uchar* obuf = NIL(uchar*);
118da2e3ebdSchin ssize_t osize = 0;
1197c2fbfb3SApril Chin SFMTXDECL(f);
120da2e3ebdSchin
121da2e3ebdSchin SFONCE();
122da2e3ebdSchin
1237c2fbfb3SApril Chin SFMTXENTER(f,NIL(Void_t*));
124da2e3ebdSchin
125da2e3ebdSchin GETLOCAL(f,local);
126da2e3ebdSchin
127da2e3ebdSchin if(size == 0 && buf)
128da2e3ebdSchin { /* special case to get buffer info */
129da2e3ebdSchin _Sfi = f->val = (f->bits&SF_MMAP) ? (f->endb-f->data) : f->size;
130da2e3ebdSchin SFMTXRETURN(f, (Void_t*)f->data);
131da2e3ebdSchin }
132da2e3ebdSchin
133da2e3ebdSchin /* cleanup actions already done, don't allow write buffering any more */
134da2e3ebdSchin if(_Sfexiting && !(f->flags&SF_STRING) && (f->mode&SF_WRITE))
135da2e3ebdSchin { buf = NIL(Void_t*);
136da2e3ebdSchin size = 0;
137da2e3ebdSchin }
138da2e3ebdSchin
139da2e3ebdSchin if((init = f->mode&SF_INIT) )
140da2e3ebdSchin { if(!f->pool && _sfsetpool(f) < 0)
141da2e3ebdSchin SFMTXRETURN(f, NIL(Void_t*));
142da2e3ebdSchin }
143da2e3ebdSchin else if((f->mode&SF_RDWR) != SFMODE(f,local) && _sfmode(f,0,local) < 0)
144da2e3ebdSchin SFMTXRETURN(f, NIL(Void_t*));
145da2e3ebdSchin
146da2e3ebdSchin if(init)
147da2e3ebdSchin f->mode = (f->mode&SF_RDWR)|SF_LOCK;
148da2e3ebdSchin else
149da2e3ebdSchin { int rv;
150da2e3ebdSchin
151da2e3ebdSchin /* make sure there is no hidden read data */
152da2e3ebdSchin if(f->proc && (f->flags&SF_READ) && (f->mode&SF_WRITE) &&
153da2e3ebdSchin _sfmode(f,SF_READ,local) < 0)
154da2e3ebdSchin SFMTXRETURN(f, NIL(Void_t*));
155da2e3ebdSchin
156da2e3ebdSchin /* synchronize first */
157da2e3ebdSchin SFLOCK(f,local); rv = SFSYNC(f); SFOPEN(f,local);
158da2e3ebdSchin if(rv < 0)
159da2e3ebdSchin SFMTXRETURN(f, NIL(Void_t*));
160da2e3ebdSchin
161da2e3ebdSchin /* turn off the SF_SYNCED bit because buffer is changing */
162da2e3ebdSchin f->mode &= ~SF_SYNCED;
163da2e3ebdSchin }
164da2e3ebdSchin
165da2e3ebdSchin SFLOCK(f,local);
166da2e3ebdSchin
167da2e3ebdSchin if((Sfio_t*)buf != f)
168da2e3ebdSchin blksz = -1;
169da2e3ebdSchin else /* setting alignment size only */
170da2e3ebdSchin { blksz = (ssize_t)size;
171da2e3ebdSchin
172da2e3ebdSchin if(!init) /* stream already initialized */
173da2e3ebdSchin { obuf = f->data;
174da2e3ebdSchin osize = f->size;
175da2e3ebdSchin goto done;
176da2e3ebdSchin }
177da2e3ebdSchin else /* initialize stream as if in the default case */
178da2e3ebdSchin { buf = NIL(Void_t*);
179da2e3ebdSchin size = (size_t)SF_UNBOUND;
180da2e3ebdSchin }
181da2e3ebdSchin }
182da2e3ebdSchin
183da2e3ebdSchin bufsize = 0;
184da2e3ebdSchin oflags = f->flags;
185da2e3ebdSchin
186da2e3ebdSchin /* see if memory mapping is possible (see sfwrite for SF_BOTH) */
187da2e3ebdSchin okmmap = (buf || (f->flags&SF_STRING) || (f->flags&SF_RDWR) == SF_RDWR) ? 0 : 1;
188da2e3ebdSchin
189da2e3ebdSchin /* save old buffer info */
190da2e3ebdSchin #ifdef MAP_TYPE
191da2e3ebdSchin if(f->bits&SF_MMAP)
192da2e3ebdSchin { if(f->data)
193da2e3ebdSchin { SFMUNMAP(f,f->data,f->endb-f->data);
194da2e3ebdSchin f->data = NIL(uchar*);
195da2e3ebdSchin }
196da2e3ebdSchin } else
197da2e3ebdSchin #endif
198da2e3ebdSchin if(f->data == f->tiny)
199da2e3ebdSchin { f->data = NIL(uchar*);
200da2e3ebdSchin f->size = 0;
201da2e3ebdSchin }
202da2e3ebdSchin obuf = f->data;
203da2e3ebdSchin osize = f->size;
204da2e3ebdSchin
205da2e3ebdSchin f->flags &= ~SF_MALLOC;
206da2e3ebdSchin f->bits &= ~SF_MMAP;
207da2e3ebdSchin
208da2e3ebdSchin /* pure read/string streams must have a valid string */
209da2e3ebdSchin if((f->flags&(SF_RDWR|SF_STRING)) == SF_RDSTR &&
210da2e3ebdSchin (size == (size_t)SF_UNBOUND || !buf))
211da2e3ebdSchin size = 0;
212da2e3ebdSchin
213da2e3ebdSchin /* set disc to the first discipline with a seekf */
214da2e3ebdSchin for(disc = f->disc; disc; disc = disc->disc)
215da2e3ebdSchin if(disc->seekf)
216da2e3ebdSchin break;
217da2e3ebdSchin
218da2e3ebdSchin if((init || local) && !(f->flags&SF_STRING))
219da2e3ebdSchin { /* ASSERT(f->file >= 0) */
220da2e3ebdSchin st.st_mode = 0;
221da2e3ebdSchin
222da2e3ebdSchin /* if has discipline, set size by discipline if possible */
223da2e3ebdSchin if(!_sys_stat || disc)
224da2e3ebdSchin { if((f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc)) < 0)
225da2e3ebdSchin goto unseekable;
226da2e3ebdSchin else
227da2e3ebdSchin { Sfoff_t e;
228da2e3ebdSchin if((e = SFSK(f,(Sfoff_t)0,SEEK_END,disc)) >= 0)
229da2e3ebdSchin f->extent = e > f->here ? e : f->here;
230da2e3ebdSchin (void)SFSK(f,f->here,SEEK_SET,disc);
231da2e3ebdSchin goto setbuf;
232da2e3ebdSchin }
233da2e3ebdSchin }
234da2e3ebdSchin
235da2e3ebdSchin /* get file descriptor status */
236da2e3ebdSchin if(sysfstatf((int)f->file,&st) < 0)
237da2e3ebdSchin f->here = -1;
238da2e3ebdSchin else
239da2e3ebdSchin {
240da2e3ebdSchin #if _sys_stat && _stat_blksize /* preferred io block size */
241da2e3ebdSchin f->blksz = (size_t)st.st_blksize;
242da2e3ebdSchin #endif
243da2e3ebdSchin bufsize = 64 * 1024;
244da2e3ebdSchin if(S_ISDIR(st.st_mode) || (Sfoff_t)st.st_size < (Sfoff_t)SF_GRAIN)
245da2e3ebdSchin okmmap = 0;
246da2e3ebdSchin if(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
247da2e3ebdSchin f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc);
248da2e3ebdSchin else f->here = -1;
249da2e3ebdSchin
250da2e3ebdSchin #if O_TEXT /* no memory mapping with O_TEXT because read()/write() alter data stream */
251da2e3ebdSchin if(okmmap && f->here >= 0 &&
252da2e3ebdSchin (sysfcntlf((int)f->file,F_GETFL,0) & O_TEXT) )
253da2e3ebdSchin okmmap = 0;
254da2e3ebdSchin #endif
255da2e3ebdSchin }
256da2e3ebdSchin
257*b30d1939SAndy Fiddaman #if SFSETLINEMODE
258da2e3ebdSchin if(init)
259*b30d1939SAndy Fiddaman f->flags |= sfsetlinemode();
260*b30d1939SAndy Fiddaman #endif
261da2e3ebdSchin
262da2e3ebdSchin if(f->here >= 0)
263da2e3ebdSchin { f->extent = (Sfoff_t)st.st_size;
264da2e3ebdSchin
265da2e3ebdSchin /* seekable std-devices are share-public by default */
266da2e3ebdSchin if(f == sfstdin || f == sfstdout || f == sfstderr)
267da2e3ebdSchin f->flags |= SF_SHARE|SF_PUBLIC;
268da2e3ebdSchin }
269da2e3ebdSchin else
270da2e3ebdSchin {
271da2e3ebdSchin unseekable:
272da2e3ebdSchin f->extent = -1;
273da2e3ebdSchin f->here = 0;
274da2e3ebdSchin
275da2e3ebdSchin if(init)
276da2e3ebdSchin { if(S_ISCHR(st.st_mode) )
277da2e3ebdSchin { int oerrno = errno;
278da2e3ebdSchin
279da2e3ebdSchin bufsize = SF_GRAIN;
280da2e3ebdSchin
281da2e3ebdSchin /* set line mode for terminals */
282da2e3ebdSchin if(!(f->flags&(SF_LINE|SF_WCWIDTH)) && isatty(f->file))
283da2e3ebdSchin f->flags |= SF_LINE|SF_WCWIDTH;
284da2e3ebdSchin #if _sys_stat
285da2e3ebdSchin else /* special case /dev/null */
286da2e3ebdSchin { reg int dev, ino;
287*b30d1939SAndy Fiddaman static int null_checked, null_dev, null_ino;
288da2e3ebdSchin dev = (int)st.st_dev;
289da2e3ebdSchin ino = (int)st.st_ino;
290*b30d1939SAndy Fiddaman if(!null_checked)
291*b30d1939SAndy Fiddaman { if(sysstatf(DEVNULL,&st) < 0)
292*b30d1939SAndy Fiddaman null_checked = -1;
293*b30d1939SAndy Fiddaman else
294*b30d1939SAndy Fiddaman { null_checked = 1;
295*b30d1939SAndy Fiddaman null_dev = (int)st.st_dev;
296*b30d1939SAndy Fiddaman null_ino = (int)st.st_ino;
297*b30d1939SAndy Fiddaman }
298*b30d1939SAndy Fiddaman }
299*b30d1939SAndy Fiddaman if(null_checked >= 0 && dev == null_dev && ino == null_ino)
300da2e3ebdSchin SFSETNULL(f);
301da2e3ebdSchin }
302da2e3ebdSchin #endif
303da2e3ebdSchin errno = oerrno;
304da2e3ebdSchin }
305da2e3ebdSchin
306da2e3ebdSchin /* initialize side buffer for r+w unseekable streams */
307da2e3ebdSchin if(!f->proc && (f->bits&SF_BOTH) )
308da2e3ebdSchin (void)_sfpopen(f,-1,-1,1);
309da2e3ebdSchin }
310da2e3ebdSchin }
311da2e3ebdSchin
312da2e3ebdSchin /* set page size, this is also the desired default buffer size */
313da2e3ebdSchin if(_Sfpage <= 0)
314da2e3ebdSchin {
315da2e3ebdSchin #if _lib_getpagesize
316da2e3ebdSchin if((_Sfpage = (size_t)getpagesize()) <= 0)
317da2e3ebdSchin #endif
318da2e3ebdSchin _Sfpage = SF_PAGE;
319da2e3ebdSchin }
320da2e3ebdSchin }
321da2e3ebdSchin
322da2e3ebdSchin #ifdef MAP_TYPE
323da2e3ebdSchin if(okmmap && size && (f->mode&SF_READ) && f->extent >= 0 )
324da2e3ebdSchin { /* see if we can try memory mapping */
325da2e3ebdSchin if(!disc)
326da2e3ebdSchin for(disc = f->disc; disc; disc = disc->disc)
327da2e3ebdSchin if(disc->readf)
328da2e3ebdSchin break;
329da2e3ebdSchin if(!disc)
330da2e3ebdSchin { f->bits |= SF_MMAP;
331da2e3ebdSchin if(size == (size_t)SF_UNBOUND)
332da2e3ebdSchin { if(bufsize > _Sfpage)
333da2e3ebdSchin size = bufsize * SF_NMAP;
334da2e3ebdSchin else size = _Sfpage * SF_NMAP;
335da2e3ebdSchin if(size > 256*1024)
336da2e3ebdSchin size = 256*1024;
337da2e3ebdSchin }
338da2e3ebdSchin }
339da2e3ebdSchin }
340da2e3ebdSchin #endif
341da2e3ebdSchin
342da2e3ebdSchin /* get buffer space */
343da2e3ebdSchin setbuf:
344da2e3ebdSchin if(size == (size_t)SF_UNBOUND)
345da2e3ebdSchin { /* define a default size suitable for block transfer */
346da2e3ebdSchin if(init && osize > 0)
347da2e3ebdSchin size = osize;
348da2e3ebdSchin else if(f == sfstderr && (f->mode&SF_WRITE))
349da2e3ebdSchin size = 0;
350da2e3ebdSchin else if(f->flags&SF_STRING )
351da2e3ebdSchin size = SF_GRAIN;
352da2e3ebdSchin else if((f->flags&SF_READ) && !(f->bits&SF_BOTH) &&
353da2e3ebdSchin f->extent > 0 && f->extent < (Sfoff_t)_Sfpage )
354da2e3ebdSchin size = (((size_t)f->extent + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
355da2e3ebdSchin else if((ssize_t)(size = _Sfpage) < bufsize)
356da2e3ebdSchin size = bufsize;
357da2e3ebdSchin
358da2e3ebdSchin buf = NIL(Void_t*);
359da2e3ebdSchin }
360da2e3ebdSchin
361da2e3ebdSchin sf_malloc = 0;
362da2e3ebdSchin if(size > 0 && !buf && !(f->bits&SF_MMAP))
363da2e3ebdSchin { /* try to allocate a buffer */
364da2e3ebdSchin if(obuf && size == (size_t)osize && init)
365da2e3ebdSchin { buf = (Void_t*)obuf;
366da2e3ebdSchin obuf = NIL(uchar*);
367da2e3ebdSchin sf_malloc = (oflags&SF_MALLOC);
368da2e3ebdSchin }
369da2e3ebdSchin if(!buf)
370da2e3ebdSchin { /* do allocation */
371da2e3ebdSchin while(!buf && size > 0)
372da2e3ebdSchin { if((buf = (Void_t*)malloc(size)) )
373da2e3ebdSchin break;
374da2e3ebdSchin else size /= 2;
375da2e3ebdSchin }
376da2e3ebdSchin if(size > 0)
377da2e3ebdSchin sf_malloc = SF_MALLOC;
378da2e3ebdSchin }
379da2e3ebdSchin }
380da2e3ebdSchin
381da2e3ebdSchin if(size == 0 && !(f->flags&SF_STRING) && !(f->bits&SF_MMAP) && (f->mode&SF_READ))
382da2e3ebdSchin { /* use the internal buffer */
383da2e3ebdSchin size = sizeof(f->tiny);
384da2e3ebdSchin buf = (Void_t*)f->tiny;
385da2e3ebdSchin }
386da2e3ebdSchin
387da2e3ebdSchin /* set up new buffer */
388da2e3ebdSchin f->size = size;
389da2e3ebdSchin f->next = f->data = f->endr = f->endw = (uchar*)buf;
390da2e3ebdSchin f->endb = (f->mode&SF_READ) ? f->data : f->data+size;
391da2e3ebdSchin if(f->flags&SF_STRING)
392da2e3ebdSchin { /* these fields are used to test actual size - see sfseek() */
393da2e3ebdSchin f->extent = (!sf_malloc &&
394da2e3ebdSchin ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ) ? size : 0;
395da2e3ebdSchin f->here = 0;
396da2e3ebdSchin
397da2e3ebdSchin /* read+string stream should have all data available */
398da2e3ebdSchin if((f->mode&SF_READ) && !sf_malloc)
399da2e3ebdSchin f->endb = f->data+size;
400da2e3ebdSchin }
401da2e3ebdSchin
402da2e3ebdSchin f->flags = (f->flags & ~SF_MALLOC)|sf_malloc;
403da2e3ebdSchin
404da2e3ebdSchin if(obuf && obuf != f->data && osize > 0 && (oflags&SF_MALLOC))
405da2e3ebdSchin { free((Void_t*)obuf);
406da2e3ebdSchin obuf = NIL(uchar*);
407da2e3ebdSchin }
408da2e3ebdSchin
409da2e3ebdSchin done:
410da2e3ebdSchin _Sfi = f->val = obuf ? osize : 0;
411da2e3ebdSchin
412da2e3ebdSchin /* blksz is used for aligning disk block boundary while reading data to
413da2e3ebdSchin ** optimize data transfer from disk (eg, via direct I/O). blksz can be
414da2e3ebdSchin ** at most f->size/2 so that data movement in buffer can be optimized.
415da2e3ebdSchin ** blksz should also be a power-of-2 for optimal disk seeks.
416da2e3ebdSchin */
417da2e3ebdSchin if(blksz <= 0 || (blksz & (blksz-1)) != 0 )
418da2e3ebdSchin blksz = SF_GRAIN;
419da2e3ebdSchin while(blksz > f->size/2)
420da2e3ebdSchin blksz /= 2;
421da2e3ebdSchin f->blksz = blksz;
422da2e3ebdSchin
423da2e3ebdSchin SFOPEN(f,local);
424da2e3ebdSchin
425da2e3ebdSchin SFMTXRETURN(f, (Void_t*)obuf);
426da2e3ebdSchin }
427