diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/hppa/stand/libsa/lif.c | 268 |
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; +} |