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