Annotation of sys/arch/mvmeppc/stand/libsa/tftpfs.c, Revision 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