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