1 1.2 riastrad /* $NetBSD: lif.c,v 1.2 2018/09/04 15:08:30 riastradh 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.2 riastrad 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