The internal_find_block command searches all entries referring to the
given filesystem data block and returns a tsk_dirent structure
for each of them.
For filesystems such as NTFS which do not delete the block mapping
when removing files, it is possible to get multiple non-allocated
entries for the same block.
The gathered list of tsk_dirent structs is serialised into XDR format
and written to a file by the appliance.
Signed-off-by: Matteo Cafasso <noxdafox(a)gmail.com>
---
daemon/tsk.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++
generator/actions.ml | 9 +++++
src/MAX_PROC_NR | 2 +-
3 files changed, 106 insertions(+), 1 deletion(-)
diff --git a/daemon/tsk.c b/daemon/tsk.c
index af803d7..afe2ed4 100644
--- a/daemon/tsk.c
+++ b/daemon/tsk.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
@@ -42,9 +43,16 @@ enum tsk_dirent_flags {
DIRENT_COMPRESSED = 0x04
};
+typedef struct {
+ bool found;
+ uint64_t block;
+} findblk_data;
+
static int open_filesystem (const char *, TSK_IMG_INFO **, TSK_FS_INFO **);
static TSK_WALK_RET_ENUM fswalk_callback (TSK_FS_FILE *, const char *, void *);
static TSK_WALK_RET_ENUM findino_callback (TSK_FS_FILE *, const char *, void *);
+static TSK_WALK_RET_ENUM findblk_callback (TSK_FS_FILE *, const char *, void *);
+static TSK_WALK_RET_ENUM attrwalk_callback (TSK_FS_FILE *, TSK_OFF_T , TSK_DADDR_T , char
*, size_t , TSK_FS_BLOCK_FLAG_ENUM , void *);
static int send_dirent_info (TSK_FS_FILE *, const char *);
static char file_type (TSK_FS_FILE *);
static int file_flags (TSK_FS_FILE *fsfile);
@@ -109,6 +117,35 @@ do_internal_find_inode (const mountable_t *mountable, int64_t inode)
return ret;
}
+int
+do_internal_find_block (const mountable_t *mountable, int64_t block)
+{
+ int ret = -1;
+ TSK_FS_INFO *fs = NULL;
+ TSK_IMG_INFO *img = NULL; /* Used internally by tsk_fs_dir_walk */
+ const int flags =
+ TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC |
+ TSK_FS_DIR_WALK_FLAG_RECURSE | TSK_FS_DIR_WALK_FLAG_NOORPHAN;
+
+ ret = open_filesystem (mountable->device, &img, &fs);
+ if (ret < 0)
+ return ret;
+
+ reply (NULL, NULL); /* Reply message. */
+
+ ret = tsk_fs_dir_walk (fs, fs->root_inum, flags,
+ findblk_callback, (void *) &block);
+ if (ret == 0)
+ ret = send_file_end (0); /* File transfer end. */
+ else
+ send_file_end (1); /* Cancel file transfer. */
+
+ fs->close (fs);
+ img->close (img);
+
+ return ret;
+}
+
/* Inspect the device and initialises the img and fs structures.
* Return 0 on success, -1 on error.
*/
@@ -172,6 +209,65 @@ findino_callback (TSK_FS_FILE *fsfile, const char *path, void *data)
return (ret == 0) ? TSK_WALK_CONT : TSK_WALK_ERROR;
}
+/* Find block, it gets called on every FS node.
+ *
+ * Return TSK_WALK_CONT on success, TSK_WALK_ERROR on error.
+ */
+static TSK_WALK_RET_ENUM
+findblk_callback (TSK_FS_FILE *fsfile, const char *path, void *data)
+{
+ findblk_data blkdata;
+ const TSK_FS_ATTR *fsattr = NULL;
+ int ret = 0, count = 0, index = 0;
+ const int flags = TSK_FS_FILE_WALK_FLAG_AONLY | TSK_FS_FILE_WALK_FLAG_SLACK |
+ TSK_FS_FILE_WALK_FLAG_NOSPARSE;
+
+ if (entry_is_dot (fsfile))
+ return TSK_WALK_CONT;
+
+ blkdata.found = false;
+ blkdata.block = * (uint64_t *) data;
+
+ /* Retrieve block list */
+ count = tsk_fs_file_attr_getsize (fsfile);
+
+ for (index = 0; index < count; index++) {
+ fsattr = tsk_fs_file_attr_get_idx (fsfile, index);
+
+ if (fsattr != NULL && fsattr->flags & TSK_FS_ATTR_NONRES) {
+ ret = tsk_fs_attr_walk (fsattr, flags,
+ attrwalk_callback, (void *) &blkdata);
+ if (ret != 0)
+ return TSK_WALK_ERROR;
+ }
+ }
+
+ if (blkdata.found)
+ ret = send_dirent_info (fsfile, path);
+
+ return (ret == 0) ? TSK_WALK_CONT : TSK_WALK_ERROR;
+}
+
+/* Attribute walk, searches the given block within the FS node attributes.
+ *
+ * Return TSK_WALK_CONT on success, TSK_WALK_ERROR on error.
+ */
+static TSK_WALK_RET_ENUM
+attrwalk_callback (TSK_FS_FILE *fsfile, TSK_OFF_T offset,
+ TSK_DADDR_T blkaddr, char *buf, size_t size,
+ TSK_FS_BLOCK_FLAG_ENUM flags, void *data)
+{
+ findblk_data *blkdata = (findblk_data *) data;
+
+ if (blkaddr == blkdata->block) {
+ blkdata->found = true;
+
+ return TSK_WALK_STOP;
+ }
+
+ return TSK_WALK_CONT;
+}
+
/* Extract the information from the entry, serialize and send it out.
* Return 0 on success, -1 on error.
*/
diff --git a/generator/actions.ml b/generator/actions.ml
index 91a1819..b38a30f 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -13253,6 +13253,15 @@ is removed." };
shortdesc = "search the entries associated to the given inode";
longdesc = "Internal function for find_inode." };
+ { defaults with
+ name = "internal_find_block"; added = (1, 35, 6);
+ style = RErr, [Mountable "device"; Int64 "block"; FileOut
"filename";], [];
+ proc_nr = Some 471;
+ visibility = VInternal;
+ optional = Some "libtsk";
+ shortdesc = "search the entries associated to the given block";
+ longdesc = "Internal function for find_block." };
+
]
(* Non-API meta-commands available only in guestfish.
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 5f476b6..c305aa5 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-470
+471
--
2.9.3