In all of the cases where we were doing pointer math to decide next pointer
[newos.git] / kernel / addons / fs / iso9660 / isofs.c
blob04b93929725e371eaa96e321337cdd5da6e5b65c
1 /*
2 ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
3 ** Distributed under the terms of the NewOS License.
4 */
5 /* Initial coding by Ithamar Adema, 2001 */
7 #include <kernel/kernel.h>
8 #include <kernel/vfs.h>
10 #include <kernel/khash.h> // for vnode hash table handling
11 #include <kernel/heap.h> // for kmalloc / kfree
12 #include <kernel/lock.h> // for mutex handling
13 #include <kernel/vm.h>
15 #include <string.h>
17 #include "isovol.h"
19 //================================================================================
20 // DEBUGGING FUNCTIONALITY
21 //================================================================================
23 #include <kernel/console.h> // for kprintf
24 #include <kernel/debug.h>
26 #define ISOFS_TRACE 0
28 #if ISOFS_TRACE
29 #define TRACE(x) kprintf x
30 #else
31 #define TRACE(x)
32 #endif
34 //================================================================================
35 // PRIVATE STRUCTURES FUNCTIONALITY
36 //================================================================================
38 #define ISOFS_HASH_SIZE 16
40 // our private filesystem structure
41 struct isofs {
42 int fd; // filedescriptor for ISO9660 file/dev
43 fs_id id; // vfs filesystem id
44 mutex lock; // lock
45 int next_vnode_id; // next available vnode id
46 void *vnode_list_hash; // hashtable of all used vnodes
47 struct isofs_vnode *root_vnode; // pointer to private vnode struct of root dir of fs
49 // ISO9660 stuff
50 char volumename[33];// name of volume
51 size_t blocksize; // Size of an ISO sector
52 long numblocks; // Number of sectors on ISO image
55 //--------------------------------------------------------------------------------
56 struct isofs_cookie {
57 struct isofs_stream *s;
58 int oflags;
59 union {
60 struct {
61 off_t pos; // Position in directory/file data
62 } file;
63 struct {
64 struct isofs_vnode* ptr;
65 } dir;
66 } u;
69 //--------------------------------------------------------------------------------
70 // our private stream structure
71 struct isofs_stream {
72 stream_type type; // is this stream a directory or file?
73 off_t desc_pos; // position in ISO of dir descriptor
74 off_t data_pos; // position in ISO of dir data
75 size_t data_len; // length of data
76 struct isofs_vnode *dir_head; // Pointer to first entry in directory
79 //--------------------------------------------------------------------------------
80 // our private vnode structure
81 struct isofs_vnode {
82 struct isofs_vnode *all_next; // next ptr of the global vnode linked-list (for hash)
83 vnode_id id; // our mapping back to vfs vnodes
84 char *name; // name of this vnode
85 struct isofs_vnode *parent; // vnode of parent (directory)
86 struct isofs_vnode *dir_next; // vnode of next entry in parent
87 struct isofs_stream stream; // private stream info
88 bool scanned; // true if dir has been scanned, false if not
91 static void iso_scan_dir(struct isofs* fs, struct isofs_vnode* dir);
93 //--------------------------------------------------------------------------------
94 static unsigned int isofs_vnode_hash_func(void *_v, const void *_key, unsigned int range)
96 struct isofs_vnode *v = _v; // convenience ptr to our vnode structure
97 const vnode_id *key = _key; // convenience ptr to vfs vnode ID
99 if(v != NULL) // If we've got a private vnode structure
100 return v->id % range; // use that to calc hash value
101 else // else
102 return (*key) % range; // use kernel vnode id
105 //--------------------------------------------------------------------------------
106 static int isofs_vnode_compare_func(void *_v, const void *_key)
108 struct isofs_vnode *v = _v; // convenience ptr to our vnode structure
109 const vnode_id *key = _key; // convenience ptr to vfs vnode ID
111 if(v->id == *key) // If the passed kernel vnode ID == private vnode ID
112 return 0; // we're the same!
113 else // else
114 return -1; // nope, not equal :(
117 //--------------------------------------------------------------------------------
118 static struct isofs_vnode *isofs_create_vnode(struct isofs *fs, const char *name)
120 struct isofs_vnode *v; // private vnode structure to be created
122 // try to allocate our private vnode structure
123 v = kmalloc(sizeof(struct isofs_vnode));
124 if(v == NULL) // return NULL if not able to
125 return NULL;
127 // initialize our vnode structure
128 memset(v, 0, sizeof(struct isofs_vnode));
129 v->id = fs->next_vnode_id++;
131 // copy name of vnode
132 v->name = kmalloc(strlen(name) + 1);
133 if(v->name == NULL) {
134 kfree(v);
135 return NULL;
137 strcpy(v->name, name);
139 // return newly allocated private vnode structure
140 return v;
143 //--------------------------------------------------------------------------------
144 static int isofs_delete_vnode(struct isofs *fs, struct isofs_vnode *v, bool force_delete)
146 // cant delete it if it's in a directory or is a directory
147 // and has children
148 //TODO:
149 // if(!force_delete && ((v->stream.type == STREAM_TYPE_DIR && v->stream.u.dir.dir_head != NULL) || v->dir_next != NULL)) {
150 // return ERR_NOT_ALLOWED;
151 // }
153 // remove it from the global hash table
154 hash_remove(fs->vnode_list_hash, v);
156 // free name if any
157 if(v->name != NULL)
158 kfree(v->name);
160 // free vnode structure itself
161 kfree(v);
163 // Tell caller all is ok
164 return 0;
167 //--------------------------------------------------------------------------------
168 static int isofs_insert_in_dir(struct isofs_vnode *dir, struct isofs_vnode *v)
170 if(dir->stream.type != STREAM_TYPE_DIR)
171 return ERR_INVALID_ARGS;
173 v->dir_next = dir->stream.dir_head;
174 dir->stream.dir_head = v;
176 v->parent = dir;
177 return 0;
180 //--------------------------------------------------------------------------------
181 static struct isofs_vnode* isofs_find_in_dir(struct isofs *fs, struct isofs_vnode* dir, const char* path)
183 struct isofs_vnode *v;
185 if(dir->stream.type != STREAM_TYPE_DIR)
186 return NULL;
188 iso_scan_dir(fs, dir);
190 for(v = dir->stream.dir_head; v; v = v->dir_next) {
191 if(strcmp(v->name, path) == 0) {
192 return v;
196 return NULL;
199 //================================================================================
200 // ISO9660 FORMAT HANDLING
201 //================================================================================
202 #define ISODIRENTRYBUF_SIZE sizeof(iso_dir_entry)+32
204 static struct isofs_vnode* iso_add_entry(struct isofs* fs, struct isofs_vnode* parent,
205 iso_dir_entry* e, off_t desc_pos)
207 struct isofs_vnode* v;
208 char name[33];
210 // Create ASCIIZ name
211 strncpy(name, e->name, e->nameLength);
212 name[e->nameLength] = '\0';
214 // Create initial vnode
215 v = isofs_create_vnode(fs,name);
217 // Fill in the stream member of the vnode
218 v->stream.type = (e->flags & 2) ? STREAM_TYPE_DIR : STREAM_TYPE_FILE;
219 v->stream.desc_pos = desc_pos;
220 v->stream.data_pos = e->dataStartSector[ISO_LSB_INDEX] * fs->blocksize;
221 v->stream.data_len = e->dataLength[ISO_LSB_INDEX];
223 // Insert it into the hierarchy
224 if (parent != NULL) {
225 isofs_insert_in_dir(parent,v);
226 } else {
227 v->parent = v;
230 // Insert it into our hashing table
231 hash_insert(fs->vnode_list_hash, v);
233 return v;
236 //--------------------------------------------------------------------------------
237 static void iso_scan_dir(struct isofs* fs, struct isofs_vnode* dir)
239 char entryBuf[ISODIRENTRYBUF_SIZE];
240 iso_dir_entry* e;
241 off_t start, end;
242 int cnt = 0;
244 if (dir->scanned) {
245 return;
248 start = dir->stream.data_pos;
249 end = start + dir->stream.data_len;
253 sys_read(fs->fd, entryBuf, start, ISODIRENTRYBUF_SIZE);
254 e = (iso_dir_entry*)&entryBuf[0];
256 if (e->recordLength == 0) {
257 break;
258 } else {
259 // Check for . and .. entries and correct name
260 if (cnt == 0 && e->nameLength <= 1 && e->name[0] < 32) {
261 strcpy(e->name, ".");
262 e->nameLength = 1;
263 } else if (cnt == 1 && e->nameLength <= 1 && e->name[0] < 32) {
264 strcpy(e->name, "..");
265 e->nameLength = 2;
268 iso_add_entry(fs, dir, e, start);
269 start += e->recordLength;
270 ++cnt;
272 } while( start < end );
274 dir->scanned = true;
277 //--------------------------------------------------------------------------------
278 static void iso_init_volume(struct isofs* fs)
280 iso_volume_descriptor voldesc;
281 iso_dir_entry* e;
283 // Read ISO9660 volume descriptor
284 sys_read(fs->fd, &voldesc, ISO_VD_START, sizeof(voldesc));
286 // Copy volume name
287 strncpy(fs->volumename, voldesc.volumeID, 32);
288 fs->volumename[32] = '\0';
290 // Copy block size + # of blocks
291 fs->blocksize = voldesc.sectorSize[ISO_LSB_INDEX];
292 fs->numblocks = voldesc.numSectors[ISO_LSB_INDEX];
294 // Get pointer to root directory entry
295 e = (iso_dir_entry*)&voldesc.rootDirEntry[0];
297 // Setup our root directory
298 fs->root_vnode = iso_add_entry(fs, NULL, e,
299 ISO_VD_START + voldesc.rootDirEntry - &voldesc.type);
302 //================================================================================
303 // VFS DRIVER API IMPLEMENTATION
304 //================================================================================
306 static int isofs_mount(fs_cookie *_fs, fs_id id, const char *device, void *args, vnode_id *root_vnid)
308 struct isofs *fs;
309 struct isofs_vnode *v;
310 int err;
312 TRACE(("isofs_mount: entry\n"));
314 fs = kmalloc(sizeof(struct isofs));
315 if(fs == NULL) {
316 err = ERR_NO_MEMORY;
317 goto err;
320 fs->id = id;
321 fs->next_vnode_id = 0;
323 // Try to open the ISO file to read
324 fs->fd = sys_open(device, 0);
325 if (fs->fd < 0) {
326 err = fs->fd;
327 goto err1;
330 err = mutex_init(&fs->lock, "isofs_mutex");
331 if(err < 0) {
332 goto err1;
335 // Create and setup hash table
336 fs->vnode_list_hash = hash_init(ISOFS_HASH_SIZE, offsetof(struct isofs_vnode, all_next),
337 &isofs_vnode_compare_func, &isofs_vnode_hash_func);
338 if(fs->vnode_list_hash == NULL) {
339 err = ERR_NO_MEMORY;
340 goto err2;
343 // Read the ISO9660 info, and create root vnode
344 iso_init_volume(fs);
346 *root_vnid = fs->root_vnode->id;
347 *_fs = fs;
349 return 0;
351 isofs_delete_vnode(fs, v, true);
352 hash_uninit(fs->vnode_list_hash);
353 err2:
354 mutex_destroy(&fs->lock);
355 err1:
356 kfree(fs);
357 err:
358 return err;
361 //--------------------------------------------------------------------------------
362 static int isofs_unmount(fs_cookie _fs)
364 struct isofs *fs = _fs;
365 struct isofs_vnode *v;
366 struct hash_iterator i;
368 TRACE(("isofs_unmount: entry fs = 0x%x\n", fs));
370 // delete all of the vnodes
371 hash_open(fs->vnode_list_hash, &i);
372 while((v = (struct isofs_vnode *)hash_next(fs->vnode_list_hash, &i)) != NULL) {
373 isofs_delete_vnode(fs, v, true);
375 hash_close(fs->vnode_list_hash, &i, false);
377 hash_uninit(fs->vnode_list_hash);
378 mutex_destroy(&fs->lock);
379 sys_close(fs->fd);
380 kfree(fs);
382 return 0;
385 //--------------------------------------------------------------------------------
386 static int isofs_sync(fs_cookie fs)
388 TRACE(("isofs_sync: entry\n"));
390 return 0;
393 //--------------------------------------------------------------------------------
394 static int isofs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *id)
396 struct isofs *fs = (struct isofs *)_fs;
397 struct isofs_vnode *dir = (struct isofs_vnode *)_dir;
398 struct isofs_vnode *v;
399 struct isofs_vnode *v1;
400 int err;
402 TRACE(("isofs_lookup: entry dir 0x%x, name '%s'\n", dir, name));
404 if(dir->stream.type != STREAM_TYPE_DIR)
405 return ERR_VFS_NOT_DIR;
407 mutex_lock(&fs->lock);
409 // look it up
410 v = isofs_find_in_dir(fs, dir, name);
411 if(!v) {
412 err = ERR_NOT_FOUND;
413 goto err;
416 err = vfs_get_vnode(fs->id, v->id, (fs_vnode *)&v1);
417 if(err < 0) {
418 goto err;
421 *id = v->id;
423 err = NO_ERROR;
425 err:
426 mutex_unlock(&fs->lock);
428 return err;
431 //--------------------------------------------------------------------------------
432 static int isofs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r)
434 struct isofs *fs = (struct isofs *)_fs;
436 TRACE(("isofs_getvnode: asking for vnode 0x%x 0x%x, r %d\n", id, r));
438 if(!r)
439 mutex_lock(&fs->lock);
441 *v = hash_lookup(fs->vnode_list_hash, &id);
443 if(!r)
444 mutex_unlock(&fs->lock);
446 TRACE(("isofs_getnvnode: looked it up at 0x%x\n", *v));
448 if(*v)
449 return 0;
450 else
451 return ERR_NOT_FOUND;
454 //--------------------------------------------------------------------------------
455 static int isofs_putvnode(fs_cookie _fs, fs_vnode _v, bool r)
457 struct isofs_vnode *v = (struct isofs_vnode *)_v;
459 TOUCH(v);
461 TRACE(("isofs_putvnode: entry on vnode 0x%x 0x%x, r %d\n", v->id, r));
463 return 0; // whatever
466 static int isofs_removevnode(fs_cookie _fs, fs_vnode _v, bool r)
468 struct isofs *fs = (struct isofs *)_fs;
469 struct isofs_vnode *v = (struct isofs_vnode *)_v;
470 int err;
472 TRACE(("isofs_removevnode: remove 0x%x (0x%x 0x%x), r %d\n", v, v->id, r));
474 if(!r)
475 mutex_lock(&fs->lock);
477 if(v->dir_next) {
478 // can't remove node if it's linked to the dir
479 panic("isofs_removevnode: vnode %p asked to be removed is present in dir\n", v);
482 isofs_delete_vnode(fs, v, false);
484 err = 0;
486 if(!r)
487 mutex_unlock(&fs->lock);
489 return err;
492 //--------------------------------------------------------------------------------
493 static int isofs_fsync(fs_cookie _fs, fs_vnode _v)
495 struct isofs_vnode *v = (struct isofs_vnode *)_v;
497 TOUCH(v);
499 TRACE(("isofs_fsync: entry on vnode 0x%x\n", v->id));
500 return 0;
503 //--------------------------------------------------------------------------------
504 static int isofs_opendir(fs_cookie _fs, fs_vnode _v, dir_cookie *_cookie)
506 struct isofs *fs = (struct isofs *)_fs;
507 struct isofs_vnode *v = (struct isofs_vnode *)_v;
508 struct isofs_cookie *cookie;
509 int err = 0;
511 TRACE(("isofs_opendir: vnode 0x%x\n", v));
513 if(v->stream.type != STREAM_TYPE_DIR)
514 return ERR_VFS_NOT_DIR;
516 cookie = kmalloc(sizeof(struct isofs_cookie));
517 if(cookie == NULL)
518 return ERR_NO_MEMORY;
520 mutex_lock(&fs->lock);
522 iso_scan_dir(fs, v);
523 cookie->u.dir.ptr = v->stream.dir_head;
525 *_cookie = cookie;
527 mutex_unlock(&fs->lock);
528 return err;
531 //--------------------------------------------------------------------------------
532 static int isofs_closedir(fs_cookie _fs, fs_vnode _v, dir_cookie _cookie)
534 struct isofs *fs = _fs;
535 struct isofs_vnode *v = _v;
536 struct isofs_cookie *cookie = _cookie;
538 TOUCH(fs);TOUCH(v);TOUCH(cookie);
540 TRACE(("isofs_closedir: entry vnode 0x%x, cookie 0x%x\n", v, cookie));
542 if(v->stream.type != STREAM_TYPE_DIR)
543 return ERR_VFS_NOT_DIR;
545 if(cookie) {
546 kfree(cookie);
549 return 0;
552 //--------------------------------------------------------------------------------
553 static int isofs_rewinddir(fs_cookie _fs, fs_vnode _v, dir_cookie _cookie)
555 struct isofs_vnode *v = _v;
556 struct isofs_cookie *cookie = _cookie;
557 int err = 0;
559 TOUCH(v);
561 TRACE(("isofs_rewinddir: vnode 0x%x, cookie 0x%x\n", v, cookie));
563 if(v->stream.type != STREAM_TYPE_DIR)
564 return ERR_VFS_NOT_DIR;
566 cookie->u.dir.ptr = cookie->s->dir_head;
568 return err;
571 //--------------------------------------------------------------------------------
572 static int isofs_readdir(fs_cookie _fs, fs_vnode _v, dir_cookie _cookie, void *buf, size_t len)
574 struct isofs *fs = _fs;
575 struct isofs_vnode *v = _v;
576 struct isofs_cookie *cookie = _cookie;
577 int err = 0;
579 TOUCH(v);
581 TRACE(("isofs_readdir: vnode 0x%x, cookie 0x%x, len 0x%x\n", v, cookie, len));
583 if(v->stream.type != STREAM_TYPE_DIR)
584 return ERR_VFS_NOT_DIR;
586 if(cookie->u.dir.ptr == NULL)
587 return 0;
589 mutex_lock(&fs->lock);
591 if(strlen(cookie->u.dir.ptr->name) + 1 > len) {
592 err = ERR_VFS_INSUFFICIENT_BUF;
593 goto err;
596 err = user_strcpy(buf, cookie->u.dir.ptr->name);
597 if(err < 0)
598 goto err;
600 err = strlen(cookie->u.dir.ptr->name) + 1;
602 cookie->u.dir.ptr = cookie->u.dir.ptr->dir_next;
604 err:
605 mutex_unlock(&fs->lock);
607 return err;
610 //--------------------------------------------------------------------------------
611 static int isofs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, int oflags)
613 struct isofs_vnode *v = _v;
614 struct isofs_cookie *cookie;
615 int err = 0;
617 TRACE(("isofs_open: vnode 0x%x, oflags 0x%x\n", v, oflags));
619 if(v->stream.type == STREAM_TYPE_DIR)
620 return ERR_VFS_IS_DIR;
622 // Allocate our cookie for storage of position
623 cookie = kmalloc(sizeof(struct isofs_cookie));
624 if(cookie == NULL) {
625 err = ERR_NO_MEMORY;
626 goto err;
629 // Setup our cookie to start of stream data
630 cookie->s = &v->stream;
631 cookie->u.file.pos = 0;
633 // Give cookie to caller
634 *_cookie = cookie;
635 err:
636 return err;
639 //--------------------------------------------------------------------------------
640 static int isofs_close(fs_cookie _fs, fs_vnode _v, file_cookie _cookie)
642 struct isofs_vnode *v = _v;
643 struct isofs_cookie *cookie = _cookie;
645 TOUCH(v); TOUCH(cookie);
647 TRACE(("isofs_close: entry vnode 0x%x, cookie 0x%x\n", v, cookie));
649 if(v->stream.type == STREAM_TYPE_DIR)
650 return ERR_VFS_IS_DIR;
652 return 0;
655 //--------------------------------------------------------------------------------
656 static int isofs_freecookie(fs_cookie _fs, fs_vnode _v, file_cookie _cookie)
658 struct isofs_vnode *v = _v;
659 struct isofs_cookie *cookie = _cookie;
661 TOUCH(v); TOUCH(cookie);
663 TRACE(("isofs_freecookie: entry vnode 0x%x, cookie 0x%x\n", v, cookie));
665 if(v->stream.type == STREAM_TYPE_DIR)
666 return ERR_VFS_IS_DIR;
668 if (cookie)
669 kfree(cookie);
671 return 0;
674 //--------------------------------------------------------------------------------
675 #define READ_CHUNK 16384
676 static ssize_t isofs_read(fs_cookie _fs, fs_vnode _v, file_cookie _cookie,
677 void *buf, off_t pos, ssize_t len)
679 struct isofs *fs = _fs;
680 struct isofs_vnode *v = _v;
681 struct isofs_cookie *cookie = _cookie;
682 ssize_t err = 0;
683 ssize_t totread = 0;
684 char *tempbuf = 0;
686 TOUCH(v);
688 TRACE(("isofs_read: vnode 0x%x, cookie 0x%x, pos 0x%x 0x%x, len 0x%x\n", v, cookie, pos, len));
690 if(v->stream.type == STREAM_TYPE_DIR)
691 return ERR_VFS_IS_DIR;
693 // If size is negative, forget it
694 if(len <= 0)
695 return 0;
697 mutex_lock(&fs->lock);
699 // If position is negative, we'll read from current pos
700 if (pos < 0) {
701 // we'll read where the cookie is at
702 pos = cookie->u.file.pos;
706 // If position is past filelength, forget it
707 if (pos >= cookie->s->data_len) {
708 err = 0;
709 goto error;
712 // If read goes partially beyond EOF
713 if (pos + len > cookie->s->data_len) {
714 // trim the read
715 len = cookie->s->data_len - pos;
718 tempbuf= kmalloc(READ_CHUNK);
719 if(!tempbuf) {
720 goto error;
723 while (len) {
724 ssize_t to_read= (READ_CHUNK< len) ? READ_CHUNK : len;
725 err = sys_read(fs->fd, tempbuf, cookie->s->data_pos + pos, to_read);
726 if(err <= 0) {
727 goto error;
729 user_memcpy(buf, tempbuf, err);
730 pos += err;
731 len -= err;
732 buf = ((char*)buf)+err;
733 totread += err;
735 // Move to next bit of the file
737 kfree(tempbuf);
738 tempbuf = 0;
739 err = totread;
740 cookie->u.file.pos = pos;
742 error:
743 mutex_unlock(&fs->lock);
744 if(tempbuf)
745 kfree(tempbuf);
747 return err;
750 //--------------------------------------------------------------------------------
751 static ssize_t isofs_write(fs_cookie fs, fs_vnode _v, file_cookie cookie, const void *buf, off_t pos, ssize_t len)
753 struct isofs_vnode *v = _v;
755 TRACE(("isofs_write: vnode 0x%x, cookie 0x%x, pos 0x%x 0x%x, len 0x%x\n", v, cookie, pos, len));
757 if(v->stream.type == STREAM_TYPE_DIR)
758 return ERR_VFS_IS_DIR;
760 return ERR_VFS_READONLY_FS;
763 //--------------------------------------------------------------------------------
764 static int isofs_seek(fs_cookie _fs, fs_vnode _v, file_cookie _cookie, off_t pos, seek_type st)
766 struct isofs *fs = _fs;
767 struct isofs_vnode *v = _v;
768 struct isofs_cookie *cookie = _cookie;
769 int err = 0;
771 TOUCH(v);
773 TRACE(("isofs_seek: vnode 0x%x, cookie 0x%x, pos 0x%x 0x%x, seek_type %d\n", v, cookie, pos, st));
775 if(v->stream.type == STREAM_TYPE_DIR)
776 return ERR_VFS_IS_DIR;
778 mutex_lock(&fs->lock);
780 switch(st) {
781 case _SEEK_SET:
782 if(pos < 0)
783 pos = 0;
784 if(pos > cookie->s->data_len)
785 pos = cookie->s->data_len;
786 cookie->u.file.pos = pos;
787 break;
788 case _SEEK_CUR:
789 if(pos + cookie->u.file.pos > cookie->s->data_len)
790 cookie->u.file.pos = cookie->s->data_len;
791 else if(pos + cookie->u.file.pos < 0)
792 cookie->u.file.pos = 0;
793 else
794 cookie->u.file.pos += pos;
795 break;
796 case _SEEK_END:
797 if(pos > 0)
798 cookie->u.file.pos = cookie->s->data_len;
799 else if(pos + cookie->s->data_len < 0)
800 cookie->u.file.pos = 0;
801 else
802 cookie->u.file.pos = pos + cookie->s->data_len;
803 break;
804 default:
805 err = ERR_INVALID_ARGS;
809 mutex_unlock(&fs->lock);
811 return err;
814 //--------------------------------------------------------------------------------
815 static int isofs_ioctl(fs_cookie _fs, fs_vnode _v, file_cookie _cookie, int op, void *buf, size_t len)
817 TRACE(("isofs_ioctl: vnode 0x%x, cookie 0x%x, op %d, buf 0x%x, len 0x%x\n", _v, _cookie, op, buf, len));
819 return ERR_INVALID_ARGS;
822 //--------------------------------------------------------------------------------
823 static int isofs_canpage(fs_cookie _fs, fs_vnode _v)
825 struct isofs_vnode *v = _v;
827 TOUCH(v);
829 TRACE(("isofs_canpage: vnode 0x%x\n", v));
831 return 0;
834 //--------------------------------------------------------------------------------
835 static ssize_t isofs_readpage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos)
837 struct isofs_vnode *v = _v;
839 TOUCH(v);
841 TRACE(("isofs_readpage: vnode 0x%x, vecs 0x%x, pos 0x%x 0x%x\n", v, vecs, pos));
843 return ERR_NOT_ALLOWED;
846 //--------------------------------------------------------------------------------
847 static int isofs_create(fs_cookie _fs, fs_vnode _dir, const char *name, void *create_args, vnode_id *new_vnid)
849 return ERR_VFS_READONLY_FS;
852 //--------------------------------------------------------------------------------
853 static int isofs_unlink(fs_cookie _fs, fs_vnode _dir, const char *name)
855 return ERR_VFS_READONLY_FS;
858 //--------------------------------------------------------------------------------
859 static int isofs_rename(fs_cookie _fs, fs_vnode _olddir, const char *oldname, fs_vnode _newdir, const char *newname)
861 return ERR_VFS_READONLY_FS;
864 //--------------------------------------------------------------------------------
865 static int isofs_mkdir(fs_cookie _fs, fs_vnode _base_dir, const char *name)
867 return ERR_VFS_READONLY_FS;
870 //--------------------------------------------------------------------------------
871 static int isofs_rmdir(fs_cookie _fs, fs_vnode _base_dir, const char *name)
873 return ERR_VFS_READONLY_FS;
876 //--------------------------------------------------------------------------------
877 static ssize_t isofs_writepage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos)
879 struct isofs_vnode *v = _v;
881 TOUCH(v);
883 TRACE(("isofs_writepage: vnode 0x%x, vecs 0x%x, pos 0x%x 0x%x\n", v, vecs, pos));
885 return ERR_NOT_ALLOWED;
888 //--------------------------------------------------------------------------------
889 static int isofs_rstat(fs_cookie _fs, fs_vnode _v, struct file_stat *stat)
891 struct isofs *fs = _fs;
892 struct isofs_vnode *v = _v;
893 int err = 0;
895 TRACE(("isofs_rstat: vnode 0x%x (0x%x 0x%x), stat 0x%x\n", v, v->id, stat));
897 mutex_lock(&fs->lock);
899 stat->vnid = v->id;
900 stat->type = v->stream.type;
902 switch(v->stream.type) {
903 case STREAM_TYPE_DIR:
904 stat->size = 0;
905 break;
906 case STREAM_TYPE_FILE:
907 stat->size = v->stream.data_len;
908 break;
909 default:
910 err = ERR_INVALID_ARGS;
911 break;
914 mutex_unlock(&fs->lock);
916 return err;
919 //--------------------------------------------------------------------------------
920 static int isofs_wstat(fs_cookie _fs, fs_vnode _v, struct file_stat *stat, int stat_mask)
922 return ERR_VFS_READONLY_FS;
925 //================================================================================
926 // REGISTRATION HANDLING
927 //================================================================================
929 static struct fs_calls isofs_calls = {
930 &isofs_mount, // mount
931 &isofs_unmount, // unmount
932 &isofs_sync, // sync
934 isofs_lookup, // lookup
936 &isofs_getvnode, // getvnode
937 &isofs_putvnode, // putvnode
938 &isofs_removevnode, // removevnode
940 &isofs_opendir, // opendir
941 &isofs_closedir, // closedir
942 &isofs_rewinddir, // rewinddir
943 &isofs_readdir, // readdir
945 &isofs_open, // open
946 &isofs_close, // close
947 &isofs_freecookie, // freecookie
948 &isofs_fsync, // fsync
950 &isofs_read, // read
951 &isofs_write, // write
952 &isofs_seek, // seek
953 &isofs_ioctl, // ioctl
955 &isofs_canpage, // canpage
956 &isofs_readpage, // readpage
957 &isofs_writepage, // writepage
959 &isofs_create, // create
960 &isofs_unlink, // unlink
961 &isofs_rename, // rename
963 &isofs_mkdir, // mkdir
964 &isofs_rmdir, // rmdir
966 &isofs_rstat, // rstat
967 &isofs_wstat // wstat
970 int fs_bootstrap(void);
972 //--------------------------------------------------------------------------------
973 int fs_bootstrap(void)
975 dprintf("bootstrap_isofs: entry\n");
976 return vfs_register_filesystem("isofs", &isofs_calls);