summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/hppa/stand/libsa/lif.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/sys/arch/hppa/stand/libsa/lif.c b/sys/arch/hppa/stand/libsa/lif.c
new file mode 100644
index 00000000000..ed4622450d7
--- /dev/null
+++ b/sys/arch/hppa/stand/libsa/lif.c
@@ -0,0 +1,268 @@
+/* $OpenBSD: lif.c,v 1.1 1998/07/30 16:01:48 mickey Exp $ */
+
+/*
+ * Copyright (c) 1998 Michael Shalayeff
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Michael Shalayeff.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <lib/libsa/stand.h>
+
+#include <machine/lifvar.h>
+
+extern int debug;
+
+struct file {
+ char f_buf[LIF_FILESTART];/* buffer for lif volume header and dir */
+ struct lifvol *f_lp; /* lif volume header pointer */
+ struct lifdir *f_ld; /* lif dir pointer */
+ int f_nfiles; /* gross number for lif dir entries */
+
+ off_t f_seek; /* seek pointer for file read */
+ struct lifdir *f_rd; /* lif dir pointer for readdir */
+
+ int f_isdir; /* special hacky flag for '.' dir */
+ int f_count; /* this file length */
+ int f_off; /* this file offset */
+};
+
+int
+lif_open (path, f)
+ char *path;
+ struct open_file *f;
+{
+ register struct file *fp;
+ register struct lifdir *dp;
+ register char *p, *q;
+ struct load load;
+ int err, buf_size, l;
+
+#ifdef LIFDEBUG
+ if (debug)
+ printf("lif_open(%s, %p)\n", path, f);
+#endif
+
+ fp = alloc(sizeof(*fp));
+ if ((err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 0,
+ sizeof(fp->f_buf), &fp->f_buf, &buf_size)) ||
+ buf_size != sizeof(fp->f_buf)) {
+#ifdef LIFDEBUG
+ if (debug)
+ printf("lif_open: unable to read LIF header (%d)\n", err);
+#endif
+ } else if ((fp->f_lp = (struct lifvol *)fp->f_buf)->vol_id == VOL_ID) {
+ f->f_fsdata = fp;
+ fp->f_ld = (struct lifdir *)(fp->f_buf + LIF_DIRSTART);
+ fp->f_seek = 0;
+ fp->f_rd = fp->f_ld;
+ fp->f_nfiles = lifstob(fp->f_lp->vol_dirsize) /
+ sizeof(struct lifdir);
+
+ /* no dirs on the lif */
+ for (p = path + (l = strlen(path)); p >= path; p--)
+ if (*p == '/') {
+ p++;
+ break;
+ }
+ if (p > path)
+ path = p;
+ } else
+ err = EINVAL;
+
+ if (!err && *path != '.') {
+ fp->f_isdir = 0;
+ err = ENOENT;
+ for (dp = fp->f_ld; dp < &fp->f_ld[fp->f_nfiles]; dp++) {
+ if (debug)
+#ifdef LIFDEBUG
+ printf("lif_open: "
+ "%s <--> '%c%c%c%c%c%c%c%c%c%c'\n",
+ path, dp->dir_name[0], dp->dir_name[1],
+ dp->dir_name[2], dp->dir_name[3],
+ dp->dir_name[4], dp->dir_name[5],
+ dp->dir_name[6], dp->dir_name[7],
+ dp->dir_name[8], dp->dir_name[9]);
+#endif
+ for (p = path, q = dp->dir_name;
+ *q && *q != ' '; q++, p++)
+ if (tolower(*q) != tolower(*p))
+ break;
+ if ((!*q || *q == ' ') && !*p) {
+ err = 0;
+ break;
+ }
+ }
+ if (!err) {
+ fp->f_off = lifstodb(dp->dir_addr);
+ if (!(err =(f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ fp->f_off, sizeof(load), &load, &buf_size)) &&
+ buf_size == sizeof(load)) {
+ /* no checksum */
+ fp->f_count = load.count - sizeof(int);
+ fp->f_off = dbtob(fp->f_off) + sizeof(load);
+#ifdef LIFDEBUG
+ if (debug)
+ printf("lif_open: %u @ %u [%x]\n",
+ fp->f_count, fp->f_off,
+ load.address);
+#endif
+ } else if (!err)
+ err = EIO;
+ }
+ } else
+ fp->f_isdir = 1;
+
+ if (err) {
+ free (fp, sizeof(*fp));
+ f->f_fsdata = NULL;
+ }
+ return err;
+}
+
+int
+lif_close(f)
+ struct open_file *f;
+{
+ free (f->f_fsdata, sizeof(struct file));
+ f->f_fsdata = NULL;
+ return 0;
+}
+
+int
+lif_read(f, buf, size, resid)
+ struct open_file *f;
+ void *buf;
+ size_t size;
+ size_t *resid;
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+ register char *p;
+ char bbuf[DEV_BSIZE];
+ size_t bsize, count = sizeof(bbuf);
+ int err = 0;
+ int foff;
+
+#ifdef LIFDEBUG
+ if (debug)
+ printf("lif_read(%p, %p, %u, %p)\n", f, buf, size, resid);
+#endif
+
+ for (p = bbuf; size; fp->f_seek += bsize, p += bsize) {
+ foff = fp->f_off + fp->f_seek;
+ if (fp->f_seek >= fp->f_count ||
+ (err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ btodb(foff), count, p, &bsize)))
+ break;
+ if (p == bbuf) {
+ bsize = sizeof(bbuf) - (foff & (sizeof(bbuf) - 1));
+ bsize = min(bsize, size);
+ bcopy(bbuf + (foff & (sizeof(bbuf) - 1)), buf, bsize);
+ p = buf;
+ }
+ count = size -= bsize;
+ }
+ if (resid)
+ *resid = size;
+
+ return err;
+}
+
+int
+lif_write(f, buf, size, resid)
+ struct open_file *f;
+ void *buf;
+ size_t size;
+ size_t *resid;
+{
+ return EOPNOTSUPP;
+}
+
+off_t
+lif_seek(f, offset, where)
+ struct open_file *f;
+ off_t offset;
+ int where;
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+
+ switch (where) {
+ case SEEK_SET:
+ fp->f_seek = offset;
+ break;
+ case SEEK_CUR:
+ fp->f_seek += offset;
+ break;
+ case SEEK_END:
+ fp->f_seek = fp->f_count - offset;
+ break;
+ default:
+ return (-1);
+ }
+ return (fp->f_seek);
+}
+
+int
+lif_stat(f, sb)
+ struct open_file *f;
+ struct stat *sb;
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+
+ sb->st_mode = 0755 | (fp->f_isdir? S_IFDIR: 0); /* XXX */
+ sb->st_uid = 0;
+ sb->st_gid = 0;
+ sb->st_size = fp->f_count;
+ return 0;
+}
+
+int
+lif_readdir(f, name)
+ struct open_file *f;
+ char *name;
+{
+ register struct file *fp = (struct file *)f->f_fsdata;
+ register char *p;
+
+ if (name) {
+ while ((fp->f_rd->dir_name[0] == ' ' ||
+ !fp->f_rd->dir_name[0]) &&
+ (fp->f_rd - fp->f_ld) < fp->f_nfiles)
+ fp->f_rd++;
+ if ((fp->f_rd - fp->f_ld) >= fp->f_nfiles) {
+ *name = '\0';
+ return -1;
+ }
+ strncpy(name, fp->f_rd->dir_name, sizeof(fp->f_rd->dir_name));
+ if ((p = strchr(name, ' ')))
+ *p = '\0';
+ fp->f_rd++;
+ } else
+ fp->f_rd = fp->f_ld;
+
+ return 0;
+}