k-tana-zero/k/iso.c

134 lines
2.9 KiB
C

#include <k/iso9660.h>
#include <k/types.h>
#include "atapi.h"
#include "fd.h"
#include "iso.h"
#include "stdio.h"
#include "string.h"
static u32 get_filename_length(const char *path, u32 *index)
{
u32 len = 0;
for (; path[*index]; ++(*index))
{
if (path[*index] != '/')
++len;
else {
while (path[*index] == '/')
++(*index);
break;
}
}
return len;
}
int open(const char *pathname, int flags)
{
if (flags != O_RDONLY)
return -1;
struct iso_prim_voldesc *iso_prim_block = read_block(ISO_PRIM_VOLDESC_BLOCK);
if (strncmp(iso_prim_block->std_identifier, "CD001", 5))
return -1;
struct iso_dir *root = &iso_prim_block->root_dir;
struct iso_dir *curr = read_block(root->data_blk.le);
u32 index = 0;
while (pathname[index] == '/')
++index;
for (int depth = 0; depth < MAX_DIR_DEPTH; ++depth)
{
char found = 0;
u32 start = index;
u32 length = get_filename_length(pathname, &index);
// we found the file
if (!length)
return register_fd(curr->data_blk.le, curr->file_size.le, 1);
// iteration for one directory
while (curr->dir_size != 0)
{
if (length == curr->idf_len &&
!strncmp(pathname + start, curr->idf, length))
{
if (!(curr->type & ISO_FILE_ISDIR))
return register_fd(curr->data_blk.le, curr->file_size.le, 0);
curr = read_block(curr->data_blk.le);
found = 1;
break;
}
else
curr = (void *)curr + curr->dir_size;
}
if (!found)
return -1;
}
return -1;
}
s64 read(int fd, void *buf, size_t count)
{
if (fd > MAX_FD)
return -1;
struct file_entry *f = &fd_table[fd];
if (!f->open)
return -1;
u32 nb_block = f->file_offset / ISO_BLOCK_SIZE;
char *content = read_block(f->lba + nb_block);
size_t i = 0;
for (; i < count && f->file_offset < f->file_size; ++i)
{
((char *)buf)[i] = content[f->file_offset];
++(f->file_offset);
if (f->file_offset / ISO_BLOCK_SIZE > nb_block)
{
++nb_block;
content = read_block(f->lba + nb_block);
}
}
return i;
}
s64 seek(int fd, u32 offset, int whence)
{
if (fd > MAX_FD)
return -1;
struct file_entry *f = &fd_table[fd];
if (!f->open)
return -1;
switch (whence)
{
case SEEK_SET:
f->file_offset = offset;
break;
case SEEK_CUR:
f->file_offset += offset;
break;
case SEEK_END:
f->file_offset = f->file_size + offset;
break;
}
return f->file_offset;
}
int close(int fd)
{
return destroy_fd(fd);
}