summaryrefslogtreecommitdiff
path: root/src/lib/libast/sfio/sfsk.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/sfsk.c
downloadksh-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.c106
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;
+ }
+}