diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/sfio/sfread.c | |
download | ksh-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.c | 140 |
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); +} |