lif.c revision 1.2 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