#include #include #include #include #include struct ofl_node { struct ofl_node *next; struct ofl_node *prev; _file_handle_t handle; }; static struct ofl_node *head_ofl_node = 0; static void _close_all_files() { for (struct ofl_node *i = head_ofl_node; i; i = i->next) _close_file(i->handle); } BEFORE_QUIT(_close_all_files) struct file { struct ofl_node *node; _file_handle_t handle; uint32_t position; uint32_t length; }; const char *remove_prefix(const char *path, uint8_t *dn_out) { if ((path[0] != 's') || (path[1] != 'd')) goto no_prefix; const char *num_part = path + 2; for (uint32_t i = 0; num_part[i]; ++i) if (num_part[i] == ':') { uint32_t dn_large; if (!try_sntoi(num_part, i, &dn_large) || dn_large > 255) goto no_prefix; *dn_out = (uint8_t)dn_large; return num_part + i + 1; } no_prefix: *dn_out = current_drive; return path; } struct file *open_file(const char *path) { uint8_t dn; path = remove_prefix(path, &dn); _file_handle_t h = _open_file(dn, path); if (!h) return 0; struct ofl_node *new_node = get_block(sizeof(struct ofl_node)); new_node->next = head_ofl_node; new_node->prev = 0; new_node->handle = h; if (head_ofl_node) head_ofl_node->prev = new_node; head_ofl_node = new_node; struct file *f = get_block(sizeof(struct file)); f->node = new_node; f->handle = h; f->position = 0; f->length = _file_size(h); return f; } void close_file(struct file *f) { _close_file(f->handle); struct ofl_node *n = f->node; if (n->next) n->next->prev = n->prev; if (n->prev) n->prev->next = n->next; if (n == head_ofl_node) head_ofl_node = n->next; free_block(n); free_block(f); } uint32_t read_from_file(struct file *f, uint32_t max, void *buf) { if (f->position + max > f->length) max = f->length - f->position; uint32_t read = _file_read(f->handle, f->position, max, buf); f->position += read; return read; } //return value and max_length don't include null terminator uint32_t read_line_from_file(struct file *f, char *sz, uint32_t max_length) { uint8_t i; for (i = 0; i < max_length; ++i) { char byte; if (!read_from_file(f, 1, &byte) || (byte == '\n')) break; sz[i] = byte; } sz[i] = '\0'; return i; } uint32_t seek_file_to(struct file *f, uint32_t to) { if (to > f->length) to = f->length; return f->position = to; } int32_t seek_file_by(struct file *f, int32_t by) { uint32_t old = f->position; uint32_t to = old + by > f->length ? f->length : old + by; f->position = to; return to - old; } __attribute__ ((pure)) uint32_t file_size(struct file *f) { return f->length; } //return value must be manually freed, unless it is a null pointer _dir_info_entry_t *get_directory_info(const char *path, uint32_t *count_out) { uint8_t dn; path = remove_prefix(path, &dn); uint32_t count = _count_of_dir(dn, path); if (!count) { *count_out = 0; return 0; } _dir_info_entry_t *buffer = get_block(count * sizeof(_dir_info_entry_t)); *count_out = _enumerate_dir(dn, path, buffer, count); return buffer; }