bootfs.c (8170B)
1 /* $Id: //depot/blt/srv/vfs/bootfs.c#9 $ 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 <stddef.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <stdio.h> 33 #include <errno.h> 34 #include <sys/stat.h> 35 #include <blt/syscall.h> 36 #include "vfs-int.h" 37 #include "bootfs.h" 38 39 static int inode_max = 0; 40 41 static struct vnode_ops bootfs_vnode_ops = 42 { 43 bootfs_read_vnode, bootfs_drop_vnode, NULL, NULL, bootfs_walk, NULL, 44 bootfs_mount, bootfs_unmount, NULL, NULL, NULL, NULL, 45 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 46 bootfs_opendir, bootfs_closedir, NULL, bootfs_rewinddir, bootfs_readdir, 47 bootfs_open, bootfs_close, bootfs_free_cookie, bootfs_read, NULL, 48 NULL, NULL, bootfs_rstat, NULL, NULL, 49 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 50 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 51 NULL, NULL, NULL, NULL 52 }; 53 54 struct fs_type bootfs = { "bootfs", &bootfs_vnode_ops, NULL }; 55 56 static struct bootfs_inode *bootfs_inew (const char *name, int offset, 57 int size) 58 { 59 struct bootfs_inode *inode; 60 61 inode = malloc (sizeof (struct bootfs_inode)); 62 inode->i_ino = inode_max++; 63 inode->i_offset = offset; 64 inode->i_size = size; 65 strlcpy (inode->i_name, name, sizeof (inode->i_name)); 66 inode->i_next = NULL; 67 return inode; 68 } 69 70 int bootfs_mount (struct superblock *super, const char *data, int silent) 71 { 72 int i; 73 struct bootfs_sb_data *sb_data; 74 struct bootfs_inode *inode; 75 boot_entry *be; 76 77 #ifdef BOOTFS_DEBUG 78 printf ("bootfs_mount\n"); 79 #endif 80 sb_data = (struct bootfs_sb_data *) malloc (sizeof (struct bootfs_sb_data)); 81 sb_data->d_bootdir_area = area_clone (3, 0, (void **) &sb_data->d_bootdir, 82 0); 83 sb_data->inode_list = NULL; 84 85 /* create inode list */ 86 sb_data->inode_list = bootfs_inew (".", 0, 0); 87 sb_data->inode_list->i_next = bootfs_inew ("..", 0, 0); 88 for (i = 0; i < BOOTDIR_MAX_ENTRIES; i++) 89 if ((sb_data->d_bootdir->bd_entry[i].be_type != BE_TYPE_NONE) && 90 strcmp (sb_data->d_bootdir->bd_entry[i].be_name, 91 BOOTDIR_DIRECTORY)) 92 { 93 be = &sb_data->d_bootdir->bd_entry[i]; 94 inode = bootfs_inew (be->be_name, be->be_offset, be->be_vsize); 95 inode->i_next = sb_data->inode_list; 96 sb_data->inode_list = inode; 97 } 98 99 super->sb_data = sb_data; 100 super->sb_root = vget (super, 0); 101 return 0; 102 } 103 104 void bootfs_unmount (struct superblock *sb) 105 { 106 #ifdef BOOTFS_DEBUG 107 printf ("bootfs_unmount\n"); 108 #endif 109 } 110 111 int bootfs_read_vnode (struct vnode *vnode) 112 { 113 struct bootfs_sb_data *sb_data; 114 struct bootfs_inode *inode; 115 116 #ifdef BOOTFS_DEBUG 117 printf ("bootfs_read_vnode %llx\n", vnode->v_vnid); 118 #endif 119 sb_data = vnode->v_sb->sb_data; 120 inode = sb_data->inode_list; 121 while (inode != NULL) 122 if (inode->i_ino == vnode->v_vnid) 123 { 124 vnode->v_data = inode; 125 return 0; 126 } 127 else 128 inode = inode->i_next; 129 130 return 0; 131 } 132 133 void bootfs_drop_vnode (struct vnode *vnode) 134 { 135 #ifdef BOOTFS_DEBUG 136 vnode->v_data = NULL; 137 #endif 138 } 139 140 struct vnode *bootfs_walk (struct vnode *parent, const char *path) 141 { 142 struct bootfs_sb_data *data; 143 struct bootfs_inode *inode; 144 145 #ifdef BOOTFS_DEBUG 146 printf ("bootfs_walk %s\n", path); 147 #endif 148 if (parent->v_vnid) 149 return NULL; 150 else 151 { 152 data = parent->v_sb->sb_data; 153 inode = data->inode_list; 154 while (inode != NULL) 155 //if (!strncmp (inode->i_name, path, BOOTDIR_NAMELEN)) 156 if (!strcmp (inode->i_name, path)) 157 return vget (parent->v_sb, inode->i_ino); 158 else 159 inode = inode->i_next; 160 return NULL; 161 } 162 } 163 164 int bootfs_opendir (struct vnode *dir, void **cookie) 165 { 166 struct bootfs_sb_data *data; 167 struct vfs_dirent_node *head, *p; 168 struct bootfs_inode *inode; 169 union bootfs_cookie *bc; 170 171 #ifdef BOOTFS_DEBUG 172 printf ("bootfs_opendir\n"); 173 #endif 174 if (dir->v_vnid) 175 return ENOTDIR; /* paranoia */ 176 177 head = NULL; 178 data = dir->v_sb->sb_data; 179 inode = data->inode_list; 180 while (inode != NULL) 181 { 182 p = malloc (sizeof (struct vfs_dirent_node)); 183 p->dirent = malloc (sizeof (struct dirent)); 184 p->dirent->d_fileno = inode->i_ino; 185 p->dirent->d_reclen = sizeof (struct dirent); 186 strncpy (p->dirent->d_name, inode->i_name, sizeof (p->dirent->d_name)); 187 188 p->next = head; 189 head = p; 190 inode = inode->i_next; 191 } 192 193 bc = malloc (sizeof (union bootfs_cookie)); 194 bc->u_dir.head = bc->u_dir.current = head; 195 *cookie = bc; 196 return 0; 197 } 198 199 void bootfs_closedir (struct vnode *dir, void *cookie) 200 { 201 #ifdef BOOTFS_DEBUG 202 printf ("bootfs_closedir\n"); 203 #endif 204 } 205 206 int bootfs_rewinddir (struct vnode *dir, void *cookie) 207 { 208 union bootfs_cookie *bc; 209 210 #ifdef BOOTFS_DEBUG 211 printf ("bootfs_rewinddir\n"); 212 #endif 213 214 bc = cookie; 215 bc->u_dir.current = bc->u_dir.head; 216 return 0; 217 } 218 219 int bootfs_readdir (struct vnode *dir, struct dirent *dirent, void *cookie) 220 { 221 struct dirent *orig; 222 union bootfs_cookie *bc; 223 224 bc = cookie; 225 if (bc->u_dir.current == NULL) 226 return 1; 227 orig = bc->u_dir.current->dirent; 228 dirent->d_fileno = orig->d_fileno; 229 dirent->d_reclen = orig->d_reclen; 230 strncpy (dirent->d_name, orig->d_name, BLT_MAX_NAME_LENGTH); 231 bc->u_dir.current = bc->u_dir.current->next; 232 #ifdef BOOTFS_DEBUG 233 printf ("bootfs_readdir %s\n", dirent->d_name); 234 #endif 235 return 0; 236 } 237 238 int bootfs_open (struct vnode *vnode, void **cookie) 239 { 240 struct bootfs_sb_data *data; 241 struct bootfs_inode *inode; 242 union bootfs_cookie *bc; 243 244 #ifdef BOOTFS_DEBUG 245 printf ("bootfs_open %llx\n", vnode->v_vnid); 246 #endif 247 data = vnode->v_sb->sb_data; 248 inode = vnode->v_data; 249 bc = malloc (sizeof (union bootfs_cookie)); 250 bc->u_file.begin = (char *) data->d_bootdir + inode->i_offset * 0x1000; 251 bc->u_file.pos = 0; 252 *cookie = bc; 253 return 0; 254 } 255 256 int bootfs_close (struct vnode *vnode, void *cookie) 257 { 258 #ifdef BOOTFS_DEBUG 259 printf ("bootfs_close %llx\n", vnode->v_vnid); 260 #endif 261 return 0; 262 } 263 264 void bootfs_free_cookie (void *cookie) 265 { 266 #ifdef BOOTFS_DEBUG 267 printf ("bootfs_free_cookie\n"); 268 #endif 269 free (cookie); 270 } 271 272 int bootfs_read (struct vnode *vnode, char *buf, size_t count, off_t offset, 273 size_t *numread, void *cookie) 274 { 275 char *src; 276 struct bootfs_sb_data *data; 277 struct bootfs_inode *inode; 278 union bootfs_cookie *bc; 279 280 #ifdef BOOTFS_DEBUG 281 printf ("bootfs_read %llx\n", vnode->v_vnid); 282 #endif 283 data = vnode->v_sb->sb_data; 284 inode = vnode->v_data; 285 bc = cookie; 286 if (offset >= inode->i_size) 287 { 288 *numread = 0; 289 return 0; 290 } 291 src = (char *) data->d_bootdir + inode->i_offset * 0x1000 + offset; 292 *numread = (count <= inode->i_size - offset) ? count : (inode->i_size - 293 offset); 294 memcpy (buf, src, *numread); 295 return 0; 296 } 297 298 int bootfs_rstat (struct vnode *vnode, struct stat *buf) 299 { 300 struct bootfs_inode *inode; 301 302 #ifdef BOOTFS_DEBUG 303 printf ("bootfs_rstat %llx\n", vnode->v_vnid); 304 #endif 305 inode = vnode->v_data; 306 307 buf->st_ino = inode->i_ino; 308 buf->st_nlink = 0; 309 buf->st_uid = 0; 310 buf->st_gid = 0; 311 buf->st_blksize = 512; 312 buf->st_size = inode->i_size; 313 buf->st_blocks = (inode->i_size & 0xfff) ? (inode->i_size >> 12) + 1 : 314 inode->i_size >> 12; 315 return 0; 316 } 317