From 35d522d38878c31005d2a4c0f4403c4baddf8099 Mon Sep 17 00:00:00 2001 From: Itay Almog Date: Fri, 21 Jan 2022 16:39:18 +0200 Subject: [PATCH 1/2] added required fixes to make ntfs work again --- stage23/fs/file.s2.c | 2 +- stage23/fs/ntfs.h | 3 ++- stage23/fs/ntfs.s2.c | 10 +++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/stage23/fs/file.s2.c b/stage23/fs/file.s2.c index 7e70b065..3f6841f9 100644 --- a/stage23/fs/file.s2.c +++ b/stage23/fs/file.s2.c @@ -114,7 +114,7 @@ struct file_handle *fopen(struct volume *part, const char *filename) { ret->fd = (void *)fd; ret->read = (void *)ntfs_read; - //ret->close = (void *)ntfs_close; + ret->close = (void *)ntfs_close; ret->size = fd->size_bytes; return ret; diff --git a/stage23/fs/ntfs.h b/stage23/fs/ntfs.h index 70ba46d7..46ab9d48 100644 --- a/stage23/fs/ntfs.h +++ b/stage23/fs/ntfs.h @@ -54,7 +54,8 @@ struct ntfs_file_handle { int ntfs_check_signature(struct volume *part); -int ntfs_open(struct ntfs_file_handle *ret, struct volume *part, const char *path); +bool ntfs_open(struct ntfs_file_handle *ret, struct volume *part, const char *path); int ntfs_read(struct ntfs_file_handle *file, void *buf, uint64_t loc, uint64_t count); +void ntfs_close(struct ntfs_file_handle *file); #endif \ No newline at end of file diff --git a/stage23/fs/ntfs.s2.c b/stage23/fs/ntfs.s2.c index 733604a6..31fcefeb 100644 --- a/stage23/fs/ntfs.s2.c +++ b/stage23/fs/ntfs.s2.c @@ -514,7 +514,7 @@ static bool ntfs_find_file_in_directory(struct ntfs_file_handle *handle, const c return false; } -int ntfs_open(struct ntfs_file_handle *ret, struct volume *part, const char *path) { +bool ntfs_open(struct ntfs_file_handle *ret, struct volume *part, const char *path) { // save the part ret->part = part; @@ -553,7 +553,7 @@ int ntfs_open(struct ntfs_file_handle *ret, struct volume *part, const char *pat // find the file in the directory entry = NULL; if (!ntfs_find_file_in_directory(ret, current_path, &entry)) - return 1; + return false; size_t filename_len = entry->name_length; @@ -582,7 +582,7 @@ int ntfs_open(struct ntfs_file_handle *ret, struct volume *part, const char *pat // save the run list memcpy(ret->run_list, (uint8_t *)attr + attr->run_offset, sizeof(ret->run_list)); - return 0; + return true; } else { // read the directory @@ -652,3 +652,7 @@ int ntfs_read(struct ntfs_file_handle *file, void *buf, uint64_t loc, uint64_t c // if we didn't read it all then we got a problem return count != 0; } + +void ntfs_close(struct ntfs_file_handle *file) { + pmm_free(file, sizeof(struct ntfs_file_handle)); +} From c74c36440a4522439ef1b2afd7fb4e916209fd41 Mon Sep 17 00:00:00 2001 From: Itay Almog Date: Fri, 21 Jan 2022 17:01:03 +0200 Subject: [PATCH 2/2] added support for resident files, this should pretty much complete a basic support for NTFS --- stage23/fs/ntfs.h | 10 +++++++-- stage23/fs/ntfs.s2.c | 50 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/stage23/fs/ntfs.h b/stage23/fs/ntfs.h index 46ab9d48..6d03db69 100644 --- a/stage23/fs/ntfs.h +++ b/stage23/fs/ntfs.h @@ -42,12 +42,18 @@ struct ntfs_file_handle { uint64_t mft_offset; uint8_t mft_run_list[256]; - // the runlist, resident index and attribute list of the - // current open file/directory + // the runlist of the open file/directory uint8_t run_list[128]; + + // The resident index, only for directories, + // could be at the same time as a runlist uint8_t resident_index_size; uint8_t resident_index[256]; + // the resident data + uint8_t resident_data_size; + uint8_t resident_data[256]; + // info about the current file uint32_t size_bytes; }; diff --git a/stage23/fs/ntfs.s2.c b/stage23/fs/ntfs.s2.c index 31fcefeb..c4c9b51f 100644 --- a/stage23/fs/ntfs.s2.c +++ b/stage23/fs/ntfs.s2.c @@ -571,16 +571,33 @@ bool ntfs_open(struct ntfs_file_handle *ret, struct volume *part, const char *pa uint8_t *attr_ptr = NULL; if (!ntfs_get_file_record_attr(file_record_buffer, FR_ATTRIBUTE_DATA, &attr_ptr)) panic(false, "NTFS: File record missing DATA attribute"); - struct file_record_attr_header_non_res *attr = (struct file_record_attr_header_non_res *)attr_ptr; + struct file_record_attr_header *attr_hdr = (struct file_record_attr_header *)attr_ptr; + + if (attr_hdr->non_res_flag) { + // this is non-resident data + struct file_record_attr_header_non_res *attr = (struct file_record_attr_header_non_res *)attr_ptr; - // verify the attr and run list are in the buffer - if ((uint8_t *)attr + sizeof(*attr) > file_record_buffer + sizeof(file_record_buffer)) - panic(false, "NTFS: File record attribute is outside of file record"); - if ((uint8_t *)attr + attr->run_offset + 256 > file_record_buffer + sizeof(file_record_buffer)) - panic(false, "NTFS: Run list is outside of file record"); + // mark that this has no resident data + ret->resident_index_size = 0; - // save the run list - memcpy(ret->run_list, (uint8_t *)attr + attr->run_offset, sizeof(ret->run_list)); + // verify the attr and run list are in the buffer + if ((uint8_t *)attr + sizeof(*attr) > file_record_buffer + sizeof(file_record_buffer)) + panic(false, "NTFS: File record attribute is outside of file record"); + if ((uint8_t *)attr + attr->run_offset + 256 > file_record_buffer + sizeof(file_record_buffer)) + panic(false, "NTFS: Run list is outside of file record"); + + // save the run list + memcpy(ret->run_list, (uint8_t *)attr + attr->run_offset, sizeof(ret->run_list)); + } else { + // this is resident data + struct file_record_attr_header_res *attr = (struct file_record_attr_header_res *)attr_ptr; + + if (attr->info_length > sizeof(ret->resident_data)) + panic(false, "NTFS: Resident data too big"); + + ret->resident_data_size = attr->info_length; + memcpy(ret->resident_data, attr + 1, attr->info_length); + } return true; @@ -602,6 +619,23 @@ int ntfs_read(struct ntfs_file_handle *file, void *buf, uint64_t loc, uint64_t c // get the runlist uint8_t *runlist = file->run_list; + // first try and handle resident data + if (file->resident_data_size != 0) { + // check bounds + if (loc > file->resident_data_size) + return 0; + + // truncate the size + if (file->resident_data_size - loc < count) { + count = file->resident_data_size - loc; + } + + // copy it + memcpy(buf, &file->resident_data[loc], count); + + return count; + } + // TODO: remember the last read location so we can have faster sequential reads... // we are going to go over the runlist until we get to the offset