Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / hp700 / stand / common / lif.c
blobb7ec3e9a1fe4c90387c1709b4bfc815f97b653c0
1 /* $NetBSD: lif.c,v 1.9 2009/10/26 19:16:55 cegger Exp $ */
3 /* $OpenBSD: lif.c,v 1.7 2001/06/09 03:54:41 mickey Exp $ */
5 /*
6 * Copyright (c) 1998-2004 Michael Shalayeff
7 * All rights reserved.
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.
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.
31 #include <sys/param.h>
32 #include <sys/disklabel.h>
33 #include "libsa.h"
35 extern int debug;
37 struct file {
38 char f_buf[HP700_LIF_FILESTART];/* buffer for lif volume header and dir */
39 struct hp700_lifvol *f_lp; /* lif volume header pointer */
40 struct hp700_lifdir *f_ld; /* lif dir pointer */
41 int f_nfiles; /* gross number for lif dir entries */
43 off_t f_seek; /* seek pointer for file read */
44 struct hp700_lifdir *f_rd; /* lif dir pointer for readdir */
46 int f_isdir; /* special hacky flag for '.' dir */
47 int f_count; /* this file length */
48 int f_off; /* this file offset */
51 int
52 lif_open(const char *path, struct open_file *f)
54 struct file *fp;
55 struct hp700_lifdir *dp;
56 const char *p, *q;
57 struct hp700_lifload load;
58 int err, l;
59 size_t buf_size;
61 #ifdef LIFDEBUG
62 if (debug)
63 printf("lif_open(%s, %p)\n", path, f);
64 #endif
66 fp = alloc(sizeof(*fp));
67 /* XXX we're assuming here that sizeof(fp->f_buf) >= HP700_LIF_FILESTART */
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 hp700_lifvol *)fp->f_buf)->vol_id ==
77 HP700_LIF_VOL_ID) {
78 f->f_fsdata = fp;
79 fp->f_ld = (struct hp700_lifdir *)(fp->f_buf + HP700_LIF_DIRSTART);
80 fp->f_seek = 0;
81 fp->f_rd = fp->f_ld;
82 fp->f_nfiles = hp700_lifstob(fp->f_lp->vol_dirsize) /
83 sizeof(struct hp700_lifdir);
85 /* no dirs on the lif */
86 for (p = path + (l = strlen(path)); p >= path; p--)
87 if (*p == '/') {
88 p++;
89 break;
91 if (p > path)
92 path = p;
93 } else
94 err = EINVAL;
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;
119 if (!err) {
120 fp->f_off = hp700_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;
136 } else
137 fp->f_isdir = 1;
139 if (err) {
140 dealloc (fp, sizeof(*fp));
141 f->f_fsdata = NULL;
143 #ifdef LIFDEBUG
144 if (debug)
145 printf("ret(%d)\n", err);
146 #endif
147 return err;
151 lif_close(struct open_file *f)
153 dealloc(f->f_fsdata, sizeof(struct file));
154 f->f_fsdata = NULL;
155 return 0;
159 lif_read(struct open_file *f, void *buf, size_t size, size_t *resid)
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;
168 #ifdef LIFDEBUG
169 if (debug)
170 printf("lif_read(%p, %p, %u, %p)\n", f, buf, size, resid);
171 #endif
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 = min(bsize, size);
183 memcpy(buf, bbuf + (foff & (sizeof(bbuf) - 1)), bsize);
184 p = buf;
186 count = size -= bsize;
188 if (resid)
189 *resid = size;
191 return err;
195 lif_write(struct open_file *f, void *buf, size_t size, size_t *resid)
197 return EOPNOTSUPP;
200 off_t
201 lif_seek(struct open_file *f, off_t offset, int where)
203 struct file *fp = (struct file *)f->f_fsdata;
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);
218 return (fp->f_seek);
222 lif_stat(struct open_file *f, struct stat *sb)
224 struct file *fp = (struct file *)f->f_fsdata;
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;
234 lif_readdir(struct open_file *f, char *name)
236 struct file *fp = (struct file *)f->f_fsdata;
237 char *p;
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;
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;
255 return 0;