Home | History | Annotate | Line # | Download | only in common
      1 /*	$NetBSD: lif.c,v 1.2 2018/09/04 15:08:30 riastradh Exp $	*/
      2 
      3 /*	$OpenBSD: lif.c,v 1.7 2001/06/09 03:54:41 mickey Exp $	*/
      4 
      5 /*
      6  * Copyright (c) 1998-2004 Michael Shalayeff
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
     22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     24  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     28  * THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include <sys/param.h>
     32 #include <sys/disklabel.h>
     33 #include "libsa.h"
     34 
     35 extern int debug;
     36 
     37 struct file {
     38 	char f_buf[HPPA_LIF_FILESTART];/* buffer for lif volume header and dir */
     39 	struct hppa_lifvol *f_lp;	/* lif volume header pointer */
     40 	struct hppa_lifdir *f_ld;	/* lif dir pointer */
     41 	int	f_nfiles;	/* gross number for lif dir entries */
     42 
     43 	off_t	f_seek;		/* seek pointer for file read */
     44 	struct hppa_lifdir *f_rd;	/* lif dir pointer for readdir */
     45 
     46 	int	f_isdir;	/* special hacky flag for '.' dir */
     47 	int	f_count;	/* this file length */
     48 	int	f_off;		/* this file offset */
     49 };
     50 
     51 int
     52 lif_open(const char *path, struct open_file *f)
     53 {
     54 	struct file *fp;
     55 	struct hppa_lifdir *dp;
     56 	const char *p, *q;
     57 	struct hppa_lifload load;
     58 	int err, l;
     59 	size_t buf_size;
     60 
     61 #ifdef LIFDEBUG
     62 	if (debug)
     63 		printf("lif_open(%s, %p)\n", path, f);
     64 #endif
     65 
     66 	fp = alloc(sizeof(*fp));
     67 	/* XXX we're assuming here that sizeof(fp->f_buf) >= HPPA_LIF_FILESTART */
     68 
     69 	err = (*f->f_dev->dv_strategy)(f->f_devdata, F_READ, 0,
     70 	    sizeof(fp->f_buf), &fp->f_buf, &buf_size);
     71 	if (err || buf_size != sizeof(fp->f_buf)) {
     72 #ifdef LIFDEBUG
     73 		if (debug)
     74 			printf("lif_open: unable to read LIF header (%d)\n", err);
     75 #endif
     76 	} else if ((fp->f_lp = (struct hppa_lifvol *)fp->f_buf)->vol_id ==
     77 		   HPPA_LIF_VOL_ID) {
     78 		f->f_fsdata = fp;
     79 		fp->f_ld = (struct hppa_lifdir *)(fp->f_buf + HPPA_LIF_DIRSTART);
     80 		fp->f_seek = 0;
     81 		fp->f_rd = fp->f_ld;
     82 		fp->f_nfiles = hppa_lifstob(fp->f_lp->vol_dirsize) /
     83 			sizeof(struct hppa_lifdir);
     84 
     85 		/* no dirs on the lif */
     86 		for (p = path + (l = strlen(path)); p >= path; p--)
     87 			if (*p == '/') {
     88 				p++;
     89 				break;
     90 			}
     91 		if (p > path)
     92 			path = p;
     93 	} else
     94 		err = EINVAL;
     95 
     96 	if (!err && *path != '.') {
     97 		fp->f_isdir = 0;
     98 		err = ENOENT;
     99 		for (dp = fp->f_ld; dp < &fp->f_ld[fp->f_nfiles]; dp++) {
    100 #ifdef LIFDEBUG
    101 			if (debug)
    102 				printf("lif_open: "
    103 				       "%s <--> '%c%c%c%c%c%c%c%c%c%c'\n",
    104 				       path, dp->dir_name[0], dp->dir_name[1],
    105 				       dp->dir_name[2], dp->dir_name[3],
    106 				       dp->dir_name[4], dp->dir_name[5],
    107 				       dp->dir_name[6], dp->dir_name[7],
    108 				       dp->dir_name[8], dp->dir_name[9]);
    109 #endif
    110 			for (p = path, q = dp->dir_name;
    111 			     *q && *q != ' '; q++, p++)
    112 				if (tolower(*q) != tolower(*p))
    113 					break;
    114 			if ((!*q || *q == ' ') && !*p) {
    115 				err = 0;
    116 				break;
    117 			}
    118 		}
    119 		if (!err) {
    120 			fp->f_off = hppa_lifstodb(dp->dir_addr);
    121 			if (!(err =(f->f_dev->dv_strategy)(f->f_devdata, F_READ,
    122 			      fp->f_off, sizeof(load), &load, &buf_size)) &&
    123 			    buf_size == sizeof(load)) {
    124 				/* no checksum */
    125 				fp->f_count = load.count - sizeof(int);
    126 				fp->f_off = dbtob(fp->f_off) + sizeof(load);
    127 #ifdef LIFDEBUG
    128 				if (debug)
    129 					printf("lif_open: %u @ %u [%x]\n",
    130 					       fp->f_count, fp->f_off,
    131 					       load.address);
    132 #endif
    133 			} else if (!err)
    134 				err = EIO;
    135 		}
    136 	} else
    137 		fp->f_isdir = 1;
    138 
    139 	if (err) {
    140 		dealloc (fp, sizeof(*fp));
    141 		f->f_fsdata = NULL;
    142 	}
    143 #ifdef LIFDEBUG
    144 	if (debug)
    145 		printf("ret(%d)\n", err);
    146 #endif
    147 	return err;
    148 }
    149 
    150 int
    151 lif_close(struct open_file *f)
    152 {
    153 	dealloc(f->f_fsdata, sizeof(struct file));
    154 	f->f_fsdata = NULL;
    155 	return 0;
    156 }
    157 
    158 int
    159 lif_read(struct open_file *f, void *buf, size_t size, size_t *resid)
    160 {
    161 	struct file *fp = (struct file *)f->f_fsdata;
    162 	char *p;
    163 	char bbuf[DEV_BSIZE];
    164 	size_t bsize, count = sizeof(bbuf);
    165 	int err = 0;
    166 	int foff;
    167 
    168 #ifdef LIFDEBUG
    169 	if (debug)
    170 		printf("lif_read(%p, %p, %zu, %p)\n", f, buf, size, resid);
    171 #endif
    172 
    173 	for (p = bbuf; size; fp->f_seek += bsize, p += bsize) {
    174 		twiddle();
    175 		foff = fp->f_off + fp->f_seek;
    176 		if (fp->f_seek >= fp->f_count ||
    177 		    (err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
    178 		     btodb(foff), count, p, &bsize)))
    179 			break;
    180 		if (p == bbuf) {
    181 			bsize = sizeof(bbuf) - (foff & (sizeof(bbuf) - 1));
    182 			bsize = uimin(bsize, size);
    183 			memcpy(buf, bbuf + (foff & (sizeof(bbuf) - 1)), bsize);
    184 			p = buf;
    185 		}
    186 		count = size -= bsize;
    187 	}
    188 	if (resid)
    189 		*resid = size;
    190 
    191 	return err;
    192 }
    193 
    194 int
    195 lif_write(struct open_file *f, void *buf, size_t size, size_t *resid)
    196 {
    197 	return EOPNOTSUPP;
    198 }
    199 
    200 off_t
    201 lif_seek(struct open_file *f, off_t offset, int where)
    202 {
    203 	struct file *fp = (struct file *)f->f_fsdata;
    204 
    205 	switch (where) {
    206 	case SEEK_SET:
    207 		fp->f_seek = offset;
    208 		break;
    209 	case SEEK_CUR:
    210 		fp->f_seek += offset;
    211 		break;
    212 	case SEEK_END:
    213 		fp->f_seek = fp->f_count - offset;
    214 		break;
    215 	default:
    216 		return (-1);
    217 	}
    218 	return (fp->f_seek);
    219 }
    220 
    221 int
    222 lif_stat(struct open_file *f, struct stat *sb)
    223 {
    224 	struct file *fp = (struct file *)f->f_fsdata;
    225 
    226 	sb->st_mode = 0755 | (fp->f_isdir? S_IFDIR: 0);	/* XXX */
    227 	sb->st_uid = 0;
    228 	sb->st_gid = 0;
    229 	sb->st_size = fp->f_count;
    230 	return 0;
    231 }
    232 
    233 int
    234 lif_readdir(struct open_file *f, char *name)
    235 {
    236 	struct file *fp = (struct file *)f->f_fsdata;
    237 	char *p;
    238 
    239 	if (name) {
    240 		while ((fp->f_rd->dir_name[0] == ' ' ||
    241 			!fp->f_rd->dir_name[0]) &&
    242 		       (fp->f_rd - fp->f_ld) < fp->f_nfiles)
    243 			fp->f_rd++;
    244 		if ((fp->f_rd - fp->f_ld) >= fp->f_nfiles) {
    245 			*name = '\0';
    246 			return -1;
    247 		}
    248 		strncpy(name, fp->f_rd->dir_name, sizeof(fp->f_rd->dir_name));
    249 		if ((p = strchr(name, ' ')))
    250 			*p = '\0';
    251 		fp->f_rd++;
    252 	} else
    253 		fp->f_rd = fp->f_ld;
    254 
    255 	return 0;
    256 }
    257