⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isofs.c

📁 newos is new operation system
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** Copyright 2001, Travis Geiselbrecht. All rights reserved.** Distributed under the terms of the NewOS License.*//* Initial coding by Ithamar Adema, 2001 */#include <kernel/kernel.h>#include <kernel/vfs.h>#include <kernel/khash.h>	// for vnode hash table handling#include <kernel/heap.h>	// for kmalloc / kfree#include <kernel/lock.h>	// for mutex handling#include <kernel/vm.h>#include <string.h>#include "isovol.h"//================================================================================// DEBUGGING FUNCTIONALITY//================================================================================#include <kernel/console.h>	// for kprintf#include <kernel/debug.h>#define ISOFS_TRACE 0#if ISOFS_TRACE#define TRACE(x) kprintf x#else#define TRACE(x)#endif//================================================================================// PRIVATE STRUCTURES FUNCTIONALITY//================================================================================#define ISOFS_HASH_SIZE 16// our private filesystem structurestruct isofs {	int fd; // filedescriptor for ISO9660 file/dev	fs_id id; // vfs filesystem id	mutex lock; // lock	int next_vnode_id; // next available vnode id	void *vnode_list_hash; // hashtable of all used vnodes	struct isofs_vnode *root_vnode; // pointer to private vnode struct of root dir of fs	// ISO9660 stuff	char volumename[33];// name of volume	size_t blocksize;	// Size of an ISO sector	long numblocks;		// Number of sectors on ISO image};//--------------------------------------------------------------------------------struct isofs_cookie {	struct isofs_stream *s;	int oflags;	union {		struct {			off_t pos;			// Position in directory/file data		} file;		struct {			struct isofs_vnode* ptr;		} dir;	} u;};//--------------------------------------------------------------------------------// our private stream structurestruct isofs_stream {	stream_type type;	// is this stream a directory or file?	off_t desc_pos;		// position in ISO of dir descriptor	off_t data_pos;		// position in ISO of dir data	size_t data_len;	// length of data	struct isofs_vnode *dir_head;	// Pointer to first entry in directory};//--------------------------------------------------------------------------------// our private vnode structurestruct isofs_vnode {	struct isofs_vnode *all_next;	// next ptr of the global vnode linked-list (for hash)	vnode_id id;					// our mapping back to vfs vnodes	char *name;						// name of this vnode	struct isofs_vnode *parent;		// vnode of parent (directory)	struct isofs_vnode *dir_next;	// vnode of next entry in parent	struct isofs_stream stream;		// private stream info	bool scanned;					// true if dir has been scanned, false if not};static void iso_scan_dir(struct isofs* fs, struct isofs_vnode* dir);//--------------------------------------------------------------------------------static unsigned int isofs_vnode_hash_func(void *_v, const void *_key, unsigned int range){	struct isofs_vnode *v = _v;	// convenience ptr to our vnode structure	const vnode_id *key = _key;	// convenience ptr to vfs vnode ID	if(v != NULL)				// If we've got a private vnode structure		return v->id % range;	//   use that to calc hash value	else						// else		return (*key) % range;	//   use kernel vnode id}//--------------------------------------------------------------------------------static int isofs_vnode_compare_func(void *_v, const void *_key){	struct isofs_vnode *v = _v;	// convenience ptr to our vnode structure	const vnode_id *key = _key;	// convenience ptr to vfs vnode ID	if(v->id == *key)			// If the passed kernel vnode ID == private vnode ID		return 0;				//    we're the same!	else						// else		return -1;				//    nope, not equal :(}//--------------------------------------------------------------------------------static struct isofs_vnode *isofs_create_vnode(struct isofs *fs, const char *name){	struct isofs_vnode *v;	// private vnode structure to be created	// try to allocate our private vnode structure	v = kmalloc(sizeof(struct isofs_vnode));	if(v == NULL) // return NULL if not able to		return NULL;	// initialize our vnode structure	memset(v, 0, sizeof(struct isofs_vnode));	v->id = fs->next_vnode_id++;	// copy name of vnode	v->name = kmalloc(strlen(name) + 1);	if(v->name == NULL) {		kfree(v);		return NULL;	}	strcpy(v->name, name);	// return newly allocated private vnode structure	return v;}//--------------------------------------------------------------------------------static int isofs_delete_vnode(struct isofs *fs, struct isofs_vnode *v, bool force_delete){	// cant delete it if it's in a directory or is a directory	// and has children//TODO://	if(!force_delete && ((v->stream.type == STREAM_TYPE_DIR && v->stream.u.dir.dir_head != NULL) || v->dir_next != NULL)) {//		return ERR_NOT_ALLOWED;//	}	// remove it from the global hash table	hash_remove(fs->vnode_list_hash, v);	// free name if any	if(v->name != NULL)		kfree(v->name);	// free vnode structure itself	kfree(v);	// Tell caller all is ok	return 0;}//--------------------------------------------------------------------------------static int isofs_insert_in_dir(struct isofs_vnode *dir, struct isofs_vnode *v){	if(dir->stream.type != STREAM_TYPE_DIR)		return ERR_INVALID_ARGS;	v->dir_next = dir->stream.dir_head;	dir->stream.dir_head = v;	v->parent = dir;	return 0;}//--------------------------------------------------------------------------------static struct isofs_vnode* isofs_find_in_dir(struct isofs *fs, struct isofs_vnode* dir, const char* path){	struct isofs_vnode *v;	if(dir->stream.type != STREAM_TYPE_DIR)		return NULL;	iso_scan_dir(fs, dir);	for(v = dir->stream.dir_head; v; v = v->dir_next) {		if(strcmp(v->name, path) == 0) {			return v;		}	}	return NULL;}//================================================================================// ISO9660 FORMAT HANDLING//================================================================================#define ISODIRENTRYBUF_SIZE	sizeof(iso_dir_entry)+32static struct isofs_vnode* iso_add_entry(struct isofs* fs, struct isofs_vnode* parent,										iso_dir_entry* e, off_t desc_pos){	struct isofs_vnode* v;	char name[33];	// Create ASCIIZ name	strncpy(name, e->name, e->nameLength);	name[e->nameLength] = '\0';	// Create initial vnode	v = isofs_create_vnode(fs,name);	// Fill in the stream member of the vnode	v->stream.type = (e->flags & 2) ? STREAM_TYPE_DIR : STREAM_TYPE_FILE;	v->stream.desc_pos = desc_pos;	v->stream.data_pos = e->dataStartSector[ISO_LSB_INDEX] * fs->blocksize;	v->stream.data_len = e->dataLength[ISO_LSB_INDEX];	// Insert it into the hierarchy	if (parent != NULL) {		isofs_insert_in_dir(parent,v);	} else {		v->parent = v;	}	// Insert it into our hashing table	hash_insert(fs->vnode_list_hash, v);	return v;}//--------------------------------------------------------------------------------static void iso_scan_dir(struct isofs* fs, struct isofs_vnode* dir){	char entryBuf[ISODIRENTRYBUF_SIZE];	iso_dir_entry* e;	off_t start, end;	int cnt = 0;	if (dir->scanned) {		return;	}	start = dir->stream.data_pos;	end = start + dir->stream.data_len;	do	{		sys_read(fs->fd, entryBuf, start, ISODIRENTRYBUF_SIZE);		e = (iso_dir_entry*)&entryBuf[0];		if (e->recordLength == 0) {			break;		} else {			// Check for . and .. entries and correct name			if (cnt == 0 && e->nameLength <= 1 && e->name[0] < 32) {				strcpy(e->name, ".");				e->nameLength = 1;			} else if (cnt == 1 && e->nameLength <= 1 && e->name[0] < 32) {				strcpy(e->name, "..");				e->nameLength = 2;			}			iso_add_entry(fs, dir, e, start);			start += e->recordLength;			++cnt;		}	} while( start < end );	dir->scanned = true;}//--------------------------------------------------------------------------------static void iso_init_volume(struct isofs* fs){	iso_volume_descriptor voldesc;	iso_dir_entry* e;	// Read ISO9660 volume descriptor	sys_read(fs->fd, &voldesc, ISO_VD_START, sizeof(voldesc));	// Copy volume name	strncpy(fs->volumename, voldesc.volumeID, 32);	fs->volumename[32] = '\0';	// Copy block size + # of blocks	fs->blocksize = voldesc.sectorSize[ISO_LSB_INDEX];	fs->numblocks = voldesc.numSectors[ISO_LSB_INDEX];	// Get pointer to root directory entry	e = (iso_dir_entry*)&voldesc.rootDirEntry[0];	// Setup our root directory	fs->root_vnode = iso_add_entry(fs, NULL, e,						ISO_VD_START + voldesc.rootDirEntry - &voldesc.type);}//================================================================================// VFS DRIVER API IMPLEMENTATION//================================================================================static int isofs_mount(fs_cookie *_fs, fs_id id, const char *device, void *args, vnode_id *root_vnid){	struct isofs *fs;	struct isofs_vnode *v;	int err;	TRACE(("isofs_mount: entry\n"));	fs = kmalloc(sizeof(struct isofs));	if(fs == NULL) {		err = ERR_NO_MEMORY;		goto err;	}	fs->id = id;	fs->next_vnode_id = 0;	// Try to open the ISO file to read	fs->fd = sys_open(device, 0);	if (fs->fd < 0) {		err = fs->fd;		goto err1;	}	err = mutex_init(&fs->lock, "isofs_mutex");	if(err < 0) {		goto err1;	}	// Create and setup hash table	fs->vnode_list_hash = hash_init(ISOFS_HASH_SIZE, offsetof(struct isofs_vnode, all_next),		&isofs_vnode_compare_func, &isofs_vnode_hash_func);	if(fs->vnode_list_hash == NULL) {		err = ERR_NO_MEMORY;		goto err2;	}	// Read the ISO9660 info, and create root vnode	iso_init_volume(fs);	*root_vnid = fs->root_vnode->id;	*_fs = fs;	return 0;	isofs_delete_vnode(fs, v, true);	hash_uninit(fs->vnode_list_hash);err2:	mutex_destroy(&fs->lock);err1:	kfree(fs);err:	return err;}//--------------------------------------------------------------------------------static int isofs_unmount(fs_cookie _fs){	struct isofs *fs = _fs;	struct isofs_vnode *v;	struct hash_iterator i;	TRACE(("isofs_unmount: entry fs = 0x%x\n", fs));	// delete all of the vnodes	hash_open(fs->vnode_list_hash, &i);	while((v = (struct isofs_vnode *)hash_next(fs->vnode_list_hash, &i)) != NULL) {		isofs_delete_vnode(fs, v, true);	}	hash_close(fs->vnode_list_hash, &i, false);	hash_uninit(fs->vnode_list_hash);	mutex_destroy(&fs->lock);	sys_close(fs->fd);	kfree(fs);	return 0;}//--------------------------------------------------------------------------------static int isofs_sync(fs_cookie fs){	TRACE(("isofs_sync: entry\n"));	return 0;}//--------------------------------------------------------------------------------static int isofs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *id){	struct isofs *fs = (struct isofs *)_fs;	struct isofs_vnode *dir = (struct isofs_vnode *)_dir;	struct isofs_vnode *v;	struct isofs_vnode *v1;	int err;	TRACE(("isofs_lookup: entry dir 0x%x, name '%s'\n", dir, name));	if(dir->stream.type != STREAM_TYPE_DIR)		return ERR_VFS_NOT_DIR;	mutex_lock(&fs->lock);	// look it up	v = isofs_find_in_dir(fs, dir, name);	if(!v) {		err = ERR_NOT_FOUND;		goto err;	}	err = vfs_get_vnode(fs->id, v->id, (fs_vnode *)&v1);	if(err < 0) {		goto err;	}	*id = v->id;	err = NO_ERROR;err:	mutex_unlock(&fs->lock);	return err;}//--------------------------------------------------------------------------------static int isofs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r){	struct isofs *fs = (struct isofs *)_fs;	TRACE(("isofs_getvnode: asking for vnode 0x%x 0x%x, r %d\n", id, r));	if(!r)		mutex_lock(&fs->lock);	*v = hash_lookup(fs->vnode_list_hash, &id);	if(!r)		mutex_unlock(&fs->lock);	TRACE(("isofs_getnvnode: looked it up at 0x%x\n", *v));	if(*v)		return 0;	else		return ERR_NOT_FOUND;}//--------------------------------------------------------------------------------static int isofs_putvnode(fs_cookie _fs, fs_vnode _v, bool r){	struct isofs_vnode *v = (struct isofs_vnode *)_v;	TOUCH(v);	TRACE(("isofs_putvnode: entry on vnode 0x%x 0x%x, r %d\n", v->id, r));	return 0; // whatever}static int isofs_removevnode(fs_cookie _fs, fs_vnode _v, bool r){	struct isofs *fs = (struct isofs *)_fs;	struct isofs_vnode *v = (struct isofs_vnode *)_v;	int err;	TRACE(("isofs_removevnode: remove 0x%x (0x%x 0x%x), r %d\n", v, v->id, r));	if(!r)		mutex_lock(&fs->lock);	if(v->dir_next) {		// can't remove node if it's linked to the dir		panic("isofs_removevnode: vnode %p asked to be removed is present in dir\n", v);	}	isofs_delete_vnode(fs, v, false);	err = 0;	if(!r)		mutex_unlock(&fs->lock);	return err;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -