From 6c3341b2a144daf256453c4ff88bae3fdd01abfe Mon Sep 17 00:00:00 2001
From: isciurus <isciurus@gmail.com>
Date: Mon, 18 Mar 2019 13:34:12 -0700
Subject: [PATCH] Read the xfs_dinode_fmt_t flags properly

---
 tsk/fs/tsk_fs.h  |  3 ++-
 tsk/fs/tsk_xfs.h |  3 ++-
 tsk/fs/xfs.cpp   | 36 +++++++++++++++++++++++++++++++-----
 3 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/tsk/fs/tsk_fs.h b/tsk/fs/tsk_fs.h
index 9f12bb8eb..ec29e5b4d 100644
--- a/tsk/fs/tsk_fs.h
+++ b/tsk/fs/tsk_fs.h
@@ -441,7 +441,8 @@ extern "C" {
         TSK_FS_META_CONTENT_TYPE_EXT4_INLINE = 0x2,   ///< Ext4 with inline data
         TSK_FS_META_CONTENT_TYPE_XFS_EXTENTS = 0x3,   ///< XFS with extents instead of individual pointers
         TSK_FS_META_CONTENT_TYPE_XFS_LOCAL = 0x4,     ///< XFS with all info stored locally instead of individual pointers
-        TSK_FS_META_CONTENT_TYPE_XFS_FMT_BTREE = 0x5  ///< XFS with all info stored in B+tree
+        TSK_FS_META_CONTENT_TYPE_XFS_FMT_BTREE = 0x5, ///< XFS with all info stored in B+tree
+        TSK_FS_META_CONTENT_TYPE_XFS_FMT_RMAP = 0x6   ///< XFS with all info stored in a reverse-mapping B+tree stored in the fork
     } TSK_FS_META_CONTENT_TYPE_ENUM;
 
 
diff --git a/tsk/fs/tsk_xfs.h b/tsk/fs/tsk_xfs.h
index 3a9e89dcf..3b1544069 100644
--- a/tsk/fs/tsk_xfs.h
+++ b/tsk/fs/tsk_xfs.h
@@ -419,7 +419,8 @@ typedef enum xfs_dinode_fmt {
      XFS_DINODE_FMT_LOCAL,
      XFS_DINODE_FMT_EXTENTS,
      XFS_DINODE_FMT_BTREE,
-     XFS_DINODE_FMT_UUID
+     XFS_DINODE_FMT_UUID,
+     XFS_DINODE_FMT_RMAP,
 } xfs_dinode_fmt_t;
 
 typedef struct xfs_dinode_core {
diff --git a/tsk/fs/xfs.cpp b/tsk/fs/xfs.cpp
index c610e7184..518d0c972 100644
--- a/tsk/fs/xfs.cpp
+++ b/tsk/fs/xfs.cpp
@@ -475,9 +475,11 @@ xfs_dinode_copy(XFSFS_INFO * xfsfs, TSK_FS_META * fs_meta,
         }
     }
 
-    if (dino_buf->di_core.di_format & XFS_DINODE_FMT_LOCAL)
+    if (tsk_verbose) { tsk_fprintf(stderr, "inode %" PRId64, inum); }
+    
+    if (dino_buf->di_core.di_format == XFS_DINODE_FMT_LOCAL)
     {
-        if (tsk_verbose) { tsk_fprintf(stderr, "dino_buf->di_format & XFS_DINODE_FMT_LOCAL == true \n"); }
+        if (tsk_verbose) { tsk_fprintf(stderr, "dino_buf->di_format == XFS_DINODE_FMT_LOCAL \n"); }
 
         fs_meta->content_type = TSK_FS_META_CONTENT_TYPE_XFS_LOCAL;
 
@@ -511,7 +513,7 @@ xfs_dinode_copy(XFSFS_INFO * xfsfs, TSK_FS_META * fs_meta,
             if (tsk_verbose) { tsk_fprintf(stderr, "unknown type = %d \n", fs_meta->type); }
         }
     }
-    else if (dino_buf->di_core.di_format & XFS_DINODE_FMT_EXTENTS)
+    else if (dino_buf->di_core.di_format == XFS_DINODE_FMT_EXTENTS)
     {
         // if inode stores extents with pointers to the blocks with data, just copy all the extents to the meta->content_ptr
 
@@ -539,8 +541,9 @@ xfs_dinode_copy(XFSFS_INFO * xfsfs, TSK_FS_META * fs_meta,
 
         memcpy(fs_meta->content_ptr, extent_data_offset, content_len);
     }
-    else {
-        if (tsk_verbose) { tsk_fprintf(stderr, "dino_buf->di_format & XFS_DINODE_FMT_EXTENTS == false (XFS_DINODE_FMT_BTREE) \n"); }
+    else if (dino_buf->di_core.di_format == XFS_DINODE_FMT_BTREE)
+    {
+        if (tsk_verbose) { tsk_fprintf(stderr, "dino_buf->di_format == XFS_DINODE_FMT_BTREE \n"); }
 
         fs_meta->content_type = TSK_FS_META_CONTENT_TYPE_XFS_FMT_BTREE;
 
@@ -548,6 +551,29 @@ xfs_dinode_copy(XFSFS_INFO * xfsfs, TSK_FS_META * fs_meta,
         Walk the b+tree
         */
     }
+    else if (dino_buf->di_core.di_format == XFS_DINODE_FMT_UUID)
+    {
+        // not used
+        
+        if (tsk_verbose) { tsk_fprintf(stderr, "dino_buf->di_format == XFS_DINODE_FMT_UUID, which is not used \n"); }
+        
+        // a stub
+        fs_meta->content_type = TSK_FS_META_CONTENT_TYPE_DEFAULT;
+    }
+    else if (dino_buf->di_core.di_format == XFS_DINODE_FMT_RMAP)
+    {
+        if (tsk_verbose) { tsk_fprintf(stderr, "dino_buf->di_format == XFS_DINODE_FMT_RMAP \n"); }
+
+        fs_meta->content_type = TSK_FS_META_CONTENT_TYPE_XFS_FMT_RMAP;
+    }
+    else
+    {
+        // shouldn't reach this state
+        if (tsk_verbose) { tsk_fprintf(stderr, "dino_buf->di_format == %d, which is an unexpected value \n"); }
+        
+        // a stub
+        fs_meta->content_type = TSK_FS_META_CONTENT_TYPE_DEFAULT;
+    }
 
     if (tsk_verbose) { tsk_fprintf(stderr, "xfs_dinode_copy: fs_meta->content_len = %d, fs_meta->content_ptr = 0x %x, fs_meta->content_type = %d \n", fs_meta->content_len, fs_meta->content_ptr, fs_meta->content_type); }
 
-- 
GitLab