Annotation of sys/arch/mvmeppc/stand/libsa/tftpfs.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: tftpfs.c,v 1.4 2006/08/13 23:08:44 miod Exp $ */
2:
3: /*-
4: * Copyright (c) 2001 Steve Murphree, Jr.
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. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by TooLs GmbH.
18: * 4. The name of TooLs GmbH may not be used to endorse or promote products
19: * derived from this software without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: /*
34: * TFTP file system.
35: */
36:
37: #include <sys/param.h>
38: #include <sys/time.h>
39: #include <sys/stat.h>
40: #include <ufs/ffs/fs.h>
41: #include <lib/libkern/libkern.h>
42:
43: #include "stand.h"
44:
45: /*
46: * In-core open file.
47: */
48: struct tftp_file {
49: char filename[128];
50: off_t f_seekp; /* seek pointer */
51: char *f_buf; /* buffer for data block */
52: off_t f_off; /* index into buffer for data block */
53: daddr_t f_buf_blkno; /* block number of data block */
54: size_t f_buf_size;
55: };
56:
57: #define TFTP_BLOCK_SHIFT 9
58: #define TFTP_BLOCK_SIZE (1<<TFTP_BLOCK_SHIFT) /* 512 by tftp convention */
59: #define TFTP_BLOCK_NO(x) ((x >> TFTP_BLOCK_SHIFT) + 1)
60: #define TFTP_BLOCK_OFF(x) (x % TFTP_BLOCK_SIZE)
61:
62: static int read_inode(ino_t, struct open_file *);
63: static int block_map(struct open_file *, daddr_t, daddr_t *);
64: static int tftp_read_file(struct open_file *, char **, size_t *);
65:
66: /*
67: * Read a portion of a file into an internal buffer. Return
68: * the location in the buffer and the amount in the buffer.
69: */
70:
71: char tftp_buf[TFTP_BLOCK_SIZE]; /* static */
72: struct tftp_file tftp_ctrl;
73:
74: static int
75: tftp_read_file(f, buf_p, size_p)
76: struct open_file *f;
77: char **buf_p; /* out */
78: size_t *size_p; /* out */
79: {
80: register struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
81: long off;
82: register daddr_t file_block;
83: size_t block_size;
84: int i, rc;
85:
86: off = TFTP_BLOCK_OFF(fp->f_seekp);
87: file_block = TFTP_BLOCK_NO(fp->f_seekp);
88: block_size = TFTP_BLOCK_SIZE;
89:
90: if (file_block == fp->f_buf_blkno + 1) {
91: /*
92: * Normal, incremental block transfer.
93: */
94: rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
95: file_block, block_size, fp->f_buf, &fp->f_buf_size);
96: if (rc)
97: return (rc);
98: if (!(file_block % 4)) /* twiddle every 4 blocks */
99: twiddle();
100: fp->f_buf_blkno = file_block;
101: } else if (file_block > fp->f_buf_blkno + 1) {
102: /*
103: * Read ahead to the requested block; If we need
104: * those we skipped, see below.
105: */
106: for (i = (fp->f_buf_blkno + 1); i <= file_block; i++) {
107: rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
108: i, block_size, fp->f_buf, &fp->f_buf_size);
109: if (rc)
110: return (rc);
111: }
112: fp->f_buf_blkno = file_block;
113: } else if (file_block < fp->f_buf_blkno) {
114: /*
115: * Uh oh... We can't rewind. Reopen the file
116: * and start again.
117: */
118: char filename[64];
119: strlcpy(filename, fp->filename, sizeof filename);
120: tftpfs_close(f);
121: tftpfs_open(filename, f);
122: for (i = 1; i <= file_block; i++) {
123: rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
124: i, block_size, fp->f_buf, &fp->f_buf_size);
125: if (rc)
126: return (rc);
127: }
128: fp->f_buf_blkno = file_block;
129: }
130:
131: /*
132: * Return address of byte in buffer corresponding to
133: * offset, and size of remainder of buffer after that
134: * byte.
135: */
136: *buf_p = fp->f_buf + off;
137: *size_p = fp->f_buf_size - off;
138:
139: /*
140: * But truncate buffer at end of file.
141: */
142: if (fp->f_buf_size > block_size){
143: twiddle();
144: return(EIO);
145: }
146:
147:
148: return (0);
149: }
150:
151: /*
152: * Open a file.
153: */
154: int
155: tftpfs_open(path, f)
156: char *path;
157: struct open_file *f;
158: {
159: struct tftp_file *fp;
160: int rc = 0;
161:
162: /* locate file system specific data structure and zero it.*/
163: fp = &tftp_ctrl;
164: bzero(fp, sizeof(struct tftp_file));
165: f->f_fsdata = (void *)fp;
166: fp->f_seekp = 0;
167: fp->f_buf = tftp_buf;
168: bzero(fp->f_buf, TFTP_BLOCK_SIZE);
169: fp->f_buf_size = 0;
170:
171: strlcpy(fp->filename, path, sizeof fp->filename);
172:
173: if (f->f_dev->dv_open == NULL) {
174: panic("No device open()!");
175: }
176: twiddle();
177: rc = (f->f_dev->dv_open)(f, path);
178: return (rc);
179: }
180:
181: int
182: tftpfs_close(f)
183: struct open_file *f;
184: {
185: register struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
186:
187: fp->f_buf = (void *)0;
188: f->f_fsdata = (void *)0;
189: (f->f_dev->dv_close)(f);
190: return (0);
191: }
192:
193: /*
194: * Copy a portion of a file into kernel memory.
195: * Cross block boundaries when necessary.
196: */
197: int
198: tftpfs_read(f, start, size, resid)
199: struct open_file *f;
200: void *start;
201: size_t size;
202: size_t *resid; /* out */
203: {
204: register struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
205: register size_t csize;
206: char *buf;
207: size_t buf_size;
208: int rc = 0;
209: register char *addr = start;
210:
211: while (size != 0) {
212: rc = tftp_read_file(f, &buf, &buf_size);
213: if (rc)
214: break;
215:
216: csize = size;
217: if (csize > buf_size)
218: csize = buf_size;
219:
220: bcopy(buf, addr, csize);
221:
222: fp->f_seekp += csize;
223: addr += csize;
224: size -= csize;
225: }
226: if (resid)
227: *resid = size;
228: return (rc);
229: }
230:
231: /*
232: * Not implemented.
233: */
234: int
235: tftpfs_write(f, start, size, resid)
236: struct open_file *f;
237: void *start;
238: size_t size;
239: size_t *resid; /* out */
240: {
241:
242: return (EROFS);
243: }
244:
245: /*
246: * We only see forward. We can't rewind.
247: */
248: off_t
249: tftpfs_seek(f, offset, where)
250: struct open_file *f;
251: off_t offset;
252: int where;
253: {
254: register struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
255:
256: switch (where) {
257: case SEEK_SET:
258: fp->f_seekp = offset;
259: break;
260: case SEEK_CUR:
261: fp->f_seekp += offset;
262: break;
263: case SEEK_END:
264: errno = EIO;
265: return (-1);
266: break;
267: default:
268: return (-1);
269: }
270: return (fp->f_seekp);
271: }
272:
273: int
274: tftpfs_stat(f, sb)
275: struct open_file *f;
276: struct stat *sb;
277: {
278: return EIO;
279: }
280:
281: #ifndef NO_READDIR
282: int
283: tftpfs_readdir (struct open_file *f, char *name)
284: {
285: return EIO;
286: }
287: #endif
288:
CVSweb