:: commit 893020f30322e5ffb36d59371fa2bb1a3a8497c9

Itay Almog <itay2828@gmail.com> — 2021-09-28 21:27

parents: 0cb083b3e4

cleanup and bufixes ntfs is weird so we can't trust the names in the index since sometimes they are wrong (?) also the read function should return 0 for success and not read size...

diff --git a/stage23/fs/ntfs.h b/stage23/fs/ntfs.h
index 373f92b8..f2e713e5 100644
--- a/stage23/fs/ntfs.h
+++ b/stage23/fs/ntfs.h
@@ -46,10 +46,6 @@ struct ntfs_file_handle {
     // current open file/directory
     uint8_t run_list[128];
 
-    bool has_resident;
-    uint8_t resident_index[256];
-    uint8_t attribute_list[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 73d25865..76ae7f04 100644
--- a/stage23/fs/ntfs.s2.c
+++ b/stage23/fs/ntfs.s2.c
@@ -60,6 +60,21 @@ struct file_record_attr_header_non_res {
     uint16_t run_offset;
 } __attribute__((packed));
 
+struct file_record_attr_name {
+    uint64_t mft_parent_record;
+    uint64_t creation_time;
+    uint64_t altered_time;
+    uint64_t mft_changed_time;
+    uint64_t read_time;
+    uint64_t allocated_size;
+    uint64_t real_size;
+    uint32_t flags;
+    uint32_t reparse;
+    uint8_t name_length;
+    uint8_t name_type;
+    uint16_t name[];
+} __attribute__((packed));
+
 struct index_record {
     char name[4];
     uint16_t update_seq_offset;
@@ -329,7 +344,7 @@ static bool ntfs_read_directory(struct ntfs_file_handle *handle, uint64_t mft_re
     dir_buffer_size = dir_size;
 
     // read the directory
-    if (ntfs_read(handle, dir_buffer, 0, dir_size) != (int)dir_size)
+    if (ntfs_read(handle, dir_buffer, 0, dir_size))
         panic("NTFS: EOF before reading directory fully...");
 
     return true;
@@ -371,13 +386,10 @@ static void ntfs_read_root(struct ntfs_file_handle *handle) {
  * Search for a file in the ntfs directory, assumes the directory has been read and is stored in
  * the temp buffer
  */
-static bool ntfs_find_file_in_directory(const char* filename, struct index_entry** out_entry) {
+static bool ntfs_find_file_in_directory(struct ntfs_file_handle *handle, const char* filename, struct index_entry** out_entry) {
     size_t dir_size = dir_buffer_size;
     uint8_t *dir_ptr = dir_buffer;
 
-    (void)filename;
-    (void)out_entry;
-    
     // TODO: iterate resident record...
 
     // get the size of the name we need to compare
@@ -419,9 +431,25 @@ static bool ntfs_find_file_in_directory(const char* filename, struct index_entry
                 break;
 
             if (filename_size == entry->name_length) {
-                // compare filename
-                for (int i = 0; i < entry->name_length; i++) {
-                    if (filename[i] != entry->name[i]) {
+                // this name seem legit, need to get the real name from the mft
+                // sometimes it works to use the index name but sometimes it has
+                // invalid names for whatever reason that I can not understand, so
+                // just always take it from the mft file record
+                uint8_t file_record_buffer[MIN_FILE_RECORD_SIZE];
+                if (!ntfs_get_file_record(handle, entry->mft_record, file_record_buffer))
+                    panic("NTFS: Failed to get file record");
+
+                uint8_t *name_attr = NULL;
+                if (!ntfs_get_file_record_attr(file_record_buffer, FR_ATTRIBUTE_NAME, &name_attr))
+                    panic("NTFS: File record missing name attribute");
+
+                // get the offset to the actual info
+                struct file_record_attr_header_res *header = (struct file_record_attr_header_res *)name_attr;
+                struct file_record_attr_name *name = (struct file_record_attr_name *)(name_attr + header->info_offset);
+
+                // compare the name
+                for (int i = 0; i < name->name_length; i++) {
+                    if (name->name[i] != filename[i]) {
                         goto next_entry;
                     }
                 }
@@ -438,9 +466,16 @@ static bool ntfs_find_file_in_directory(const char* filename, struct index_entry
             index_size -= entry->entry_size;
         }
 
-        // next record
-        dir_ptr += index_record->index_entry_size;
-        dir_size -= index_record->index_entry_size;
+        // next record, need to do some rounding
+        index_size = index_record->index_entry_size;
+        if (index_size < 0x1000) {
+            index_size = 0x1000;
+        } else {
+            index_size = (index_size + 0x100) & 0xffffff00;
+        }
+
+        dir_ptr += index_size;
+        dir_size -= index_size;
     }
 
     return false;
@@ -478,11 +513,13 @@ int ntfs_open(struct ntfs_file_handle *ret, struct volume *part, const char *pat
     struct index_entry* entry = NULL;
     for (;;) {
         // skip slash
-        current_path++;
+        while (*current_path == '\\' || *current_path == '/') {
+            current_path++;
+        }
         
         // find the file in the directory
         entry = NULL;
-        if (!ntfs_find_file_in_directory(current_path, &entry))
+        if (!ntfs_find_file_in_directory(ret, current_path, &entry))
             return 1;
 
         size_t filename_len = entry->name_length;
@@ -532,10 +569,11 @@ 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;
 
+    // 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
     // once we get to the offset we are going to continue going over
     // the runlist while copying bytes
-    uint64_t wanted_to_read = count;
     uint64_t bytes_per_cluster = file->bpb.sectors_per_cluster * file->bpb.bytes_per_sector;
     do {
         // get the next element from the runlist
@@ -578,6 +616,6 @@ int ntfs_read(struct ntfs_file_handle *file, void *buf, uint64_t loc, uint64_t c
         }
     } while(count);
 
-    // return how much we read...
-    return wanted_to_read - count;
+    // if we didn't read it all then we got a problem
+    return count != 0;
 }
tab: 248 wrap: offon