#include #include #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); }