rawfs.c revision 1.4 1 /* $NetBSD: rawfs.c,v 1.4 2001/11/09 18:27:59 scw Exp $ */
2
3 /*
4 * Copyright (c) 1995 Gordon W. Ross
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 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 * 4. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Gordon W. Ross
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Raw file system - for stream devices like tapes.
35 * No random access, only sequential read allowed.
36 * This exists only to allow upper level code to be
37 * shielded from the fact that the device must be
38 * read only with whole block position and size.
39 */
40
41 #include <sys/param.h>
42 #include <stand.h>
43 #include <rawfs.h>
44
45 extern int debug;
46
47 #define RAWFS_BSIZE 8192
48
49 /*
50 * In-core open file.
51 */
52 struct file {
53 daddr_t fs_nextblk; /* block number to read next */
54 daddr_t fs_curblk; /* block number currently in buffer */
55 int fs_len; /* amount left in f_buf */
56 char * fs_ptr; /* read pointer into f_buf */
57 char fs_buf[RAWFS_BSIZE];
58 };
59
60 static int
61 rawfs_get_block __P((struct open_file *));
62
63 int rawfs_open(path, f)
64 char *path;
65 struct open_file *f;
66 {
67 struct file *fs;
68
69 /*
70 * The actual PROM driver has already been opened.
71 * Just allocate the I/O buffer, etc.
72 */
73 fs = alloc(sizeof(struct file));
74 fs->fs_nextblk = 0;
75 fs->fs_curblk = -1;
76 fs->fs_len = 0;
77 fs->fs_ptr = fs->fs_buf;
78
79 f->f_fsdata = fs;
80 return (0);
81 }
82
83 int rawfs_close(f)
84 struct open_file *f;
85 {
86 struct file *fs;
87
88 fs = (struct file *) f->f_fsdata;
89 f->f_fsdata = (void *)0;
90
91 if (fs != (struct file *)0)
92 free(fs, sizeof(*fs));
93
94 return (0);
95 }
96
97 int rawfs_read(f, start, size, resid)
98 struct open_file *f;
99 void *start;
100 u_int size;
101 u_int *resid;
102 {
103 struct file *fs = (struct file *)f->f_fsdata;
104 char *addr = start;
105 int error = 0;
106 size_t csize;
107
108 while (size != 0) {
109
110 if (fs->fs_len == 0)
111 if ((error = rawfs_get_block(f)) != 0)
112 break;
113
114 if (fs->fs_len <= 0)
115 break; /* EOF */
116
117 csize = size;
118 if (csize > fs->fs_len)
119 csize = fs->fs_len;
120
121 memcpy(addr, fs->fs_ptr, csize);
122 fs->fs_ptr += csize;
123 fs->fs_len -= csize;
124 addr += csize;
125 size -= csize;
126 }
127 if (resid)
128 *resid = size;
129
130 if (error) {
131 errno = error;
132 error = -1;
133 }
134
135 return (error);
136 }
137
138 int rawfs_write(f, start, size, resid)
139 struct open_file *f;
140 void *start;
141 size_t size;
142 size_t *resid; /* out */
143 {
144 errno = EROFS;
145 return (-1);
146 }
147
148 off_t rawfs_seek(f, offset, where)
149 struct open_file *f;
150 off_t offset;
151 int where;
152 {
153 struct file *fs = (struct file *)f->f_fsdata;
154 daddr_t curblk, targblk;
155 off_t newoff;
156 int err, idx;
157
158 /*
159 * We support a very minimal feature set for lseek(2); just
160 * enough to allow loadfile() to work with the parameters
161 * we pass to it on boot.
162 *
163 * In all cases, we can't seek back past the start of the
164 * current block.
165 */
166 curblk = (fs->fs_curblk < 0) ? 0 : fs->fs_curblk;
167
168 /*
169 * Only support SEEK_SET and SEEK_CUR which result in offsets
170 * which don't require seeking backwards.
171 */
172 switch (where) {
173 case SEEK_SET:
174 newoff = offset;
175 break;
176
177 case SEEK_CUR:
178 if (fs->fs_curblk < 0)
179 newoff = 0;
180 else {
181 newoff = fs->fs_curblk * RAWFS_BSIZE;
182 newoff += RAWFS_BSIZE - fs->fs_len;
183 }
184 newoff += offset;
185 break;
186
187 default:
188 errno = EINVAL;
189 return (-1);
190 }
191
192 if (newoff < (curblk * RAWFS_BSIZE)) {
193 errno = EINVAL;
194 return (-1);
195 }
196
197 targblk = newoff / RAWFS_BSIZE;
198
199 /*
200 * If necessary, skip blocks until we hit the required target
201 */
202 err = 0;
203 while (fs->fs_curblk != targblk && (err = rawfs_get_block(f)) == 0)
204 ;
205
206 if (err) {
207 errno = err;
208 return (-1);
209 }
210
211 /*
212 * Update the index within the loaded block
213 */
214 idx = newoff % RAWFS_BSIZE;
215 fs->fs_len = RAWFS_BSIZE - idx;
216 fs->fs_ptr = &fs->fs_buf[idx];
217
218 return (newoff);
219 }
220
221 int rawfs_stat(f, sb)
222 struct open_file *f;
223 struct stat *sb;
224 {
225 errno = EFTYPE;
226 return (-1);
227 }
228
229
230 /*
231 * Read a block from the underlying stream device
232 * (In our case, a tape drive.)
233 */
234 static int
235 rawfs_get_block(f)
236 struct open_file *f;
237 {
238 struct file *fs;
239 int error, len;
240
241 fs = (struct file *)f->f_fsdata;
242 fs->fs_ptr = fs->fs_buf;
243
244 twiddle();
245 error = f->f_dev->dv_strategy(f->f_devdata, F_READ,
246 fs->fs_nextblk * (RAWFS_BSIZE / DEV_BSIZE),
247 RAWFS_BSIZE, fs->fs_buf, &len);
248
249 if (!error) {
250 fs->fs_len = len;
251 fs->fs_curblk = fs->fs_nextblk;
252 fs->fs_nextblk += 1;
253 } else {
254 errno = error;
255 error = -1;
256 }
257
258 return (error);
259 }
260