openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

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