file.c (5319B)
1 /* $Id: //depot/blt/srv/vfs/drivers/ffs/file.c#2 $ 2 ** 3 ** Copyright 1999 Sidney Cammeresi 4 ** All rights reserved. 5 ** 6 ** Redistribution and use in source and binary forms, with or without 7 ** modification, are permitted provided that the following conditions 8 ** are met: 9 ** 1. Redistributions of source code must retain the above copyright 10 ** notice, this list of conditions, and the following disclaimer. 11 ** 2. Redistributions in binary form must reproduce the above copyright 12 ** notice, this list of conditions, and the following disclaimer in the 13 ** documentation and/or other materials provided with the distribution. 14 ** 3. The name of the author may not be used to endorse or promote products 15 ** derived from this software without specific prior written permission. 16 ** 17 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include "vfs-int.h" 33 34 #ifndef VFS_SANDBOX 35 #include <blt/blkdev.h> 36 #else 37 #include "../../sandbox/blkdev.h" 38 #endif 39 40 #include "ffs.h" 41 #include "ffs-blt.h" 42 #include "dinode.h" 43 44 int ffs_open (struct vnode *vnode, void **cookie) 45 { 46 struct ffs_super_data *data; 47 struct ffs_dinode *inode; 48 struct ffs_cookie *fc; 49 50 #ifdef FFS_DEBUG 51 printf ("ffs_open %lld\n", vnode->v_vnid); 52 #endif 53 data = vnode->v_sb->sb_data; 54 inode = vnode->v_data; 55 fc = malloc (sizeof (struct ffs_cookie)); 56 *cookie = fc; 57 return 0; 58 } 59 60 int ffs_close (struct vnode *vnode, void *cookie) 61 { 62 #ifdef FFS_DEBUG 63 printf ("ffs_close %lld\n", vnode->v_vnid); 64 #endif 65 return 0; 66 } 67 68 void ffs_free_cookie (void *cookie) 69 { 70 #ifdef FFS_DEBUG 71 printf ("ffs_free_cookie\n"); 72 #endif 73 free (cookie); 74 } 75 76 static inline int32 ffs_fbtofsb (struct ffs_super *fs, blkdev_t *dev, 77 struct ffs_dinode *di, uint32 fb) 78 { 79 int32 *buf, res; 80 81 if (fb < NDADDR) 82 return di->di_db[fb]; 83 else if ((fb -= NDADDR) < NINDIR (fs)) 84 { 85 buf = malloc (BLKSIZE); 86 blk_read (dev, buf, fsbtodb (fs, di->di_ib[0]), BLKSIZE / dev->blksize); 87 res = buf[fb]; 88 free (buf); 89 return res; 90 } 91 else if ((fb -= NINDIR (fs)) < NINDIR (fs) * NINDIR (fs)) 92 { 93 printf ("ffs: doubly indirect blocks unsupported.\n"); 94 return 0; 95 } 96 else if ((fb -= NINDIR (fs) * NINDIR (fs)) < NINDIR (fs) * NINDIR (fs) * 97 NINDIR (fs)) 98 { 99 printf ("ffs: trebly indirect blocks unsupported.\n"); 100 return 0; 101 } 102 else 103 return -1; 104 } 105 106 int ffs_read (struct vnode *vnode, char *buf, size_t count, off_t pos, 107 size_t *numbytes, void *cookie) 108 { 109 char *temp; 110 int i, block; 111 off_t offset, len; 112 struct ffs_super *fs; 113 struct ffs_super_data *data; 114 struct ffs_dinode *di; 115 116 #ifdef FFS_DEBUG 117 printf ("ffs_read %lld %d\n", pos, count); 118 #endif 119 *numbytes = 0; 120 if (!count) 121 return 0; 122 data = vnode->v_sb->sb_data; 123 fs = data->sbbuf; 124 di = vnode->v_data; 125 if (pos >= di->di_size) 126 return 0; 127 if (pos + count > di->di_size) 128 count = di->di_size - pos; 129 temp = malloc (BLKSIZE); 130 131 /* 132 * if we are not starting at a block boundary, first read up to the 133 * next block boundary. 134 */ 135 if ((offset = pos % BLKSIZE)) 136 { 137 block = ffs_fbtofsb (fs, data->dev, di, pos / BLKSIZE); 138 len = (count < (BLKSIZE - offset)) ? count : (BLKSIZE - offset); 139 blk_read (data->dev, temp, fsbtodb (fs, block), BLKSIZE / 140 data->dev->blksize); 141 memcpy (buf, temp + offset, len); 142 *numbytes += len, pos += len; 143 #ifdef FFS_DEBUG 144 printf ("ffs_read: (1) %lld\n", len); 145 #endif 146 } 147 if (*numbytes == count) 148 goto done; 149 150 /* 151 * now we are block-aligned; read whole blocks at a time until we have 152 * less than a full block to go. 153 */ 154 for (i = 0; i < ((count - *numbytes) / BLKSIZE); i++, *numbytes += BLKSIZE, 155 pos += BLKSIZE) 156 { 157 block = ffs_fbtofsb (fs, data->dev, di, pos / BLKSIZE); 158 blk_read (data->dev, temp, fsbtodb (fs, block), BLKSIZE / 159 data->dev->blksize); 160 memcpy (buf + *numbytes, temp, BLKSIZE); 161 #ifdef FFS_DEBUG 162 printf ("ffs_read: (2) #%d\n", i); 163 #endif 164 } 165 if (*numbytes == count) 166 goto done; 167 168 /* 169 * read in the next block and copy as much as we need. 170 */ 171 block = ffs_fbtofsb (fs, data->dev, di, pos / BLKSIZE); 172 blk_read (data->dev, temp, fsbtodb (fs, block), BLKSIZE / 173 data->dev->blksize); 174 memcpy (buf + *numbytes, temp, len = count - *numbytes); 175 *numbytes += len, pos += len; 176 #ifdef FFS_DEBUG 177 printf ("ffs_read: (3) %lld\n", len); 178 #endif 179 180 done: 181 free (temp); 182 return 0; 183 } 184 185 int ffs_rstat (struct vnode *vnode, struct stat *buf) 186 { 187 struct ffs_dinode *di; 188 #ifdef FFS_DEBUG 189 printf ("ffs_rstat %lld\n", vnode->v_vnid); 190 #endif 191 192 di = vnode->v_data; 193 buf->st_ino = vnode->v_vnid; 194 buf->st_nlink = di->di_nlink; 195 buf->st_uid = di->di_uid; 196 buf->st_gid = di->di_gid; 197 buf->st_size = di->di_size; 198 buf->st_blocks = di->di_blocks; 199 return 0; 200 } 201