summaryrefslogtreecommitdiff
path: root/src/lib/libast/sfio/sfread.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/sfio/sfread.c
downloadksh-upstream.tar.gz
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/sfio/sfread.c')
-rw-r--r--src/lib/libast/sfio/sfread.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/lib/libast/sfio/sfread.c b/src/lib/libast/sfio/sfread.c
new file mode 100644
index 0000000..a3aed97
--- /dev/null
+++ b/src/lib/libast/sfio/sfread.c
@@ -0,0 +1,140 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read n bytes from a stream into a buffer
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+ssize_t sfread(Sfio_t* f, Void_t* buf, size_t n)
+#else
+ssize_t sfread(f,buf,n)
+Sfio_t* f; /* read from this stream. */
+Void_t* buf; /* buffer to read into */
+size_t n; /* number of bytes to be read. */
+#endif
+{
+ reg uchar *s, *begs;
+ reg ssize_t r;
+ reg int local, justseek;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (ssize_t)(-1));
+
+ GETLOCAL(f,local);
+ justseek = f->bits&SF_JUSTSEEK; f->bits &= ~SF_JUSTSEEK;
+
+ if(!buf)
+ SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) );
+
+ /* release peek lock */
+ if(f->mode&SF_PEEK)
+ { if(!(f->mode&SF_READ) )
+ SFMTXRETURN(f, (ssize_t)(-1));
+
+ if(f->mode&SF_GETR)
+ { if(((uchar*)buf + f->val) != f->next &&
+ (!f->rsrv || f->rsrv->data != (uchar*)buf) )
+ SFMTXRETURN(f, (ssize_t)(-1));
+ f->mode &= ~SF_PEEK;
+ SFMTXRETURN(f, 0);
+ }
+ else
+ { if((uchar*)buf != f->next)
+ SFMTXRETURN(f, (ssize_t)(-1));
+ f->mode &= ~SF_PEEK;
+ if(f->mode&SF_PKRD)
+ { /* actually read the data now */
+ f->mode &= ~SF_PKRD;
+ if(n > 0)
+ n = (r = sysreadf(f->file,f->data,n)) < 0 ? 0 : r;
+ f->endb = f->data+n;
+ f->here += n;
+ }
+ f->next += n;
+ f->endr = f->endb;
+ SFMTXRETURN(f, n);
+ }
+ }
+
+ s = begs = (uchar*)buf;
+ for(;; f->mode &= ~SF_LOCK)
+ { /* check stream mode */
+ if(SFMODE(f,local) != SF_READ && _sfmode(f,SF_READ,local) < 0)
+ { n = s > begs ? s-begs : (size_t)(-1);
+ SFMTXRETURN(f, (ssize_t)n);
+ }
+
+ SFLOCK(f,local);
+
+ if((r = f->endb - f->next) > 0) /* has buffered data */
+ { if(r > (ssize_t)n)
+ r = (ssize_t)n;
+ if(s != f->next)
+ memcpy(s, f->next, r);
+ f->next += r;
+ s += r;
+ n -= r;
+ }
+
+ if(n <= 0) /* all done */
+ break;
+
+ if(!(f->flags&SF_STRING) && !(f->bits&SF_MMAP) )
+ { f->next = f->endb = f->data;
+
+ /* exact IO is desirable for these cases */
+ if(SFDIRECT(f,n) ||
+ ((f->flags&SF_SHARE) && f->extent < 0) )
+ r = (ssize_t)n;
+ else if(justseek && n <= f->iosz && f->iosz <= f->size)
+ r = f->iosz; /* limit buffering */
+ else r = f->size; /* full buffering */
+
+ /* if read almost full size, then just do it direct */
+ if(r > (ssize_t)n && (r - r/8) <= (ssize_t)n)
+ r = (ssize_t)n;
+
+ /* read directly to user's buffer */
+ if(r == (ssize_t)n && (r = SFRD(f,s,r,f->disc)) >= 0)
+ { s += r;
+ n -= r;
+ if(r == 0 || n == 0) /* eof or eob */
+ break;
+ }
+ else goto do_filbuf;
+ }
+ else
+ { do_filbuf:
+ if(justseek)
+ f->bits |= SF_JUSTSEEK;
+ if(SFFILBUF(f,-1) <= 0)
+ break;
+ }
+ }
+
+ SFOPEN(f,local);
+ r = s-begs;
+ SFMTXRETURN(f, r);
+}