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/sfsk.c | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/sfio/sfsk.c')
-rw-r--r-- | src/lib/libast/sfio/sfsk.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/lib/libast/sfio/sfsk.c b/src/lib/libast/sfio/sfsk.c new file mode 100644 index 0000000..4b82a4d --- /dev/null +++ b/src/lib/libast/sfio/sfsk.c @@ -0,0 +1,106 @@ +/*********************************************************************** +* * +* 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" + +/* Seek function that knows discipline +** +** Written by Kiem-Phong Vo. +*/ +#if __STD_C +Sfoff_t sfsk(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc) +#else +Sfoff_t sfsk(f,addr,type,disc) +Sfio_t* f; +Sfoff_t addr; +int type; +Sfdisc_t* disc; +#endif +{ + Sfoff_t p; + reg Sfdisc_t* dc; + reg ssize_t s; + reg int local, mode; + SFMTXDECL(f); + + SFMTXENTER(f, (Sfoff_t)(-1)); + + GETLOCAL(f,local); + if(!local && !(f->bits&SF_DCDOWN)) + { if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0) + SFMTXRETURN(f, (Sfoff_t)(-1)); + if(SFSYNC(f) < 0) + SFMTXRETURN(f, (Sfoff_t)(-1)); +#ifdef MAP_TYPE + if(f->mode == SF_READ && (f->bits&SF_MMAP) && f->data) + { SFMUNMAP(f, f->data, f->endb-f->data); + f->data = NIL(uchar*); + } +#endif + f->next = f->endb = f->endr = f->endw = f->data; + } + + if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) > SEEK_END) + SFMTXRETURN(f, (Sfoff_t)(-1)); + + for(;;) + { dc = disc; + if(f->flags&SF_STRING) + { SFSTRSIZE(f); + if(type == SEEK_SET) + s = (ssize_t)addr; + else if(type == SEEK_CUR) + s = (ssize_t)(addr + f->here); + else s = (ssize_t)(addr + f->extent); + } + else + { SFDISC(f,dc,seekf); + if(dc && dc->seekf) + { SFDCSK(f,addr,type,dc,p); + } + else + { p = syslseekf(f->file,(sfoff_t)addr,type); + } + if(p >= 0) + SFMTXRETURN(f,p); + s = -1; + } + + if(local) + SETLOCAL(f); + switch(_sfexcept(f,SF_SEEK,s,dc)) + { + case SF_EDISC: + case SF_ECONT: + if(f->flags&SF_STRING) + SFMTXRETURN(f, (Sfoff_t)s); + goto do_continue; + default: + SFMTXRETURN(f, (Sfoff_t)(-1)); + } + + do_continue: + for(dc = f->disc; dc; dc = dc->disc) + if(dc == disc) + break; + disc = dc; + } +} |