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 35extern int debug; 36 37struct 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 51int 52lif_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 150int 151lif_close(struct open_file *f) 152{ 153 dealloc(f->f_fsdata, sizeof(struct file)); 154 f->f_fsdata = NULL; 155 return 0; 156} 157 158int 159lif_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 194int 195lif_write(struct open_file *f, void *buf, size_t size, size_t *resid) 196{ 197 return EOPNOTSUPP; 198} 199 200off_t 201lif_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 221int 222lif_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 233int 234lif_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