:: commit 02ea23abfa5a7cb4b1eb9b00a72ad8a2ba25bc6c

Itay Almog <itay2828@gmail.com> — 2021-09-29 13:56

parents: 6cd265b497

Runlist elements are relative to the last runlist, so make that work

diff --git a/stage23/fs/ntfs.s2.c b/stage23/fs/ntfs.s2.c
index 76ae7f04..79d8b35d 100644
--- a/stage23/fs/ntfs.s2.c
+++ b/stage23/fs/ntfs.s2.c
@@ -193,41 +193,36 @@ static bool ntfs_get_next_run_list_element(uint8_t **runlist, uint64_t *out_clus
         return false;
     }
 
-    uint8_t low = runlist_ptr[0] & 0xF;
-    uint8_t high = (runlist_ptr[0] >> 4) & 0xF;
+    uint8_t count_size = runlist_ptr[0] & 0xF;
+    uint8_t cluster_size = (runlist_ptr[0] >> 4) & 0xF;
     runlist_ptr++;
 
     // get the run length
     uint64_t count = 0;
-    for (int i = low; i > 0; i--) {
+    for (int i = count_size; i > 0; i--) {
         count <<= 8;
         count |= runlist_ptr[i - 1];
     }
-    runlist_ptr += low;
-
-    // get the high byte first
-    int8_t high_byte = (int8_t)runlist_ptr[high - 1];
+    runlist_ptr += count_size;
 
     // get the run offset
-    uint64_t cluster = 0;
-    for (int i = high; i > 0; i--) {
+    int64_t cluster = 0;
+    for (int i = cluster_size; i > 0; i--) {
         cluster <<= 8;
         cluster |= runlist_ptr[i - 1];
     }
-    runlist_ptr += high;
-
-    // if the offset is negative, fill the empty bytes with 0xff
-    if (high_byte < 0 && high < 8) {
-        uint64_t fill = 0;
-        for (int i = 8; i > high; i--) {
-            fill >>= 8;
-            fill |= 0xFF00000000000000;
+    runlist_ptr += cluster_size;
+
+    // sign exten the run offset
+    if (cluster >> (cluster_size * 8 - 1)) {
+        for (int i = 7; i >= cluster_size; i--) {
+            cluster |= (uint64_t)0xFF << (i * 8);
         }
-        cluster |= fill;
     }
 
-    // out it
-    *out_cluster = cluster;
+    // out it, the cluster is relative to the last cluster
+    // so add it
+    *out_cluster += cluster;
     *out_cluster_count = count;
 
     // update it 
@@ -577,8 +572,8 @@ int ntfs_read(struct ntfs_file_handle *file, void *buf, uint64_t loc, uint64_t c
     uint64_t bytes_per_cluster = file->bpb.sectors_per_cluster * file->bpb.bytes_per_sector;
     do {
         // get the next element from the runlist
-        uint64_t cluster_count;
-        uint64_t cluster;
+        uint64_t cluster = 0;
+        uint64_t cluster_count = 0;
         if (!ntfs_get_next_run_list_element(&runlist, &cluster_count, &cluster, true))
             break;
 
tab: 248 wrap: offon